package cn.xyz.mianshi.service.impl;

import cn.xyz.commons.constants.DBConstants;
import cn.xyz.commons.constants.KConstants;
import cn.xyz.commons.constants.MsgType;
import cn.xyz.commons.ex.ServiceException;
import cn.xyz.commons.support.Callback;
import cn.xyz.commons.support.mongo.MongoOperator;
import cn.xyz.commons.utils.*;
import cn.xyz.commons.vo.JSONMessage;
import cn.xyz.mianshi.model.PageResult;
import cn.xyz.mianshi.model.PageVO;
import cn.xyz.mianshi.model.RoomVO;
import cn.xyz.mianshi.service.RoomManager;
import cn.xyz.mianshi.utils.ConstantUtil;
import cn.xyz.mianshi.utils.SKBeanUtils;
import cn.xyz.mianshi.vo.*;
import cn.xyz.mianshi.vo.GroupHelper.KeyWord;
import cn.xyz.mianshi.vo.Room.Member;
import cn.xyz.mianshi.vo.Room.MemberRate;
import cn.xyz.mianshi.vo.Room.Notice;
import cn.xyz.mianshi.vo.Room.Share;
import cn.xyz.repository.mongo.MongoRepository;
import cn.xyz.service.KXMPPServiceImpl;
import cn.xyz.service.KXMPPServiceImpl.MessageBean;
import cn.xyz.service.RedisServiceImpl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mongodb.*;
import com.mongodb.client.*;
import com.shiku.commons.thread.ThreadUtils;
import org.apache.commons.collections.map.HashedMap;
import org.apache.poi.ss.usermodel.Workbook;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.jivesoftware.smackx.muc.packet.MUCAdmin;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.mapping.MappedClass;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.UpdateOperations;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import sun.rmi.runtime.Log;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.*;
import java.util.regex.Pattern;

@Service(RoomManager.BEAN_ID)
public class RoomManagerImplForIM extends MongoRepository<Room, ObjectId> implements RoomManager {

	 private static final Logger logger = LoggerFactory.getLogger(RoomManagerImplForIM.class);
	private MongoDatabase imRoomDatabase;

    @Qualifier(value ="imRoomMongoClient")
	@Autowired(required=false)
	private MongoClient imRoomMongoClient;

	private MongoDatabase roomJidsDB;


	@Override
	public Datastore getDatastore() { return SKBeanUtils.getImRoomDatastore(); }

	@Override
	public Class<Room> getEntityClass() {
		return Room.class;
	}


	public MongoDatabase getImRoomDatabase(){
		if(null==imRoomDatabase)
			imRoomDatabase = imRoomMongoClient.getDatabase(DBConstants.IMROOM_DB);
		return imRoomDatabase;
	}




	private static UserManagerImpl getUserManager(){
		UserManagerImpl userManager = SKBeanUtils.getUserManager();
		return userManager;
	};
	
	private static RedisServiceImpl getRedisServiceImpl(){

		return SKBeanUtils.getRedisService();
	}


	
	@Override
	public String getCollectionName() {
		MappedClass mappedClass = morphia.getMapper().getMappedClass(Member.class);
		if(null==mappedClass)
			return null;
		return mappedClass.getCollectionName();
	}

	@Override
	public String getCollectionName(ObjectId id) {
		if (null == id) {
			logger.info(" ====  getCollectionName ObjectId is null  ====");
			throw new ServiceException("ObjectId  is  null !");
		} else {
			int remainder = 0;
			int counter = id.getCounter();

			remainder = counter / KConstants.DB_REMAINDER.MEMBER;
			return String.valueOf(remainder);
		}
	}

	@Override
	public String getCollectionName(int userId) {
		int remainder=0;
		if(userId>KConstants.MIN_USERID) {
			remainder=(userId/KConstants.DB_REMAINDER.MEMBER);
		}
		return String.valueOf(remainder);
	}

	public MongoCollection<Document> getCollection(int userId){
		String collectionName = getCollectionName(userId);
		logger.info("[ww]collectionName="+roomJidsDB);
		if(null==roomJidsDB)
			roomJidsDB = SKBeanUtils.getLocalSpringBeanManager().getMongoClient().getDatabase(DBConstants.SHIKU_ROOMJIDS_USERID);
		return roomJidsDB.getCollection(collectionName);
	}

	/**
	 * @return
	 */
	private Datastore getRoomDatastore() {
		// TODO Auto-generated method stub
		return SKBeanUtils.getImRoomDatastore();
	}

	@Override
	public Room add(User user, Room entity, List<Integer> memberUserIdList,JSONObject userKeys) {
		Config config = SKBeanUtils.getSystemConfig();
		
		user.setNum(user.getNum()+1);

		logger.info("[ww]Room.add user.getNickname()="+user.getNickname());
		entity.initRoomConfig(user.getUserId(),user.getNickname()); // 初始化群组配置
		List<Role> userRoles = SKBeanUtils.getRoleManager().getUserRoles(user.getUserId(), null, 0);
		if(null != userRoles && userRoles.size()>0){
			for(Role role : userRoles){
				if(role.getRole() == 4){
					entity.setPromotionUrl(role.getPromotionUrl());
				}
			}
		}

		if (null == entity.getName())
			entity.setName("我的群组");
		if (null == entity.getDesc())
			entity.setDesc("");

		if (null == entity.getLongitude())
			entity.setLongitude(0d);
		if (null == entity.getLatitude())
			entity.setLatitude(0d);

		if (StringUtil.isEmpty(entity.getJid())){
			entity.setJid(StringUtil.randomUUID());
		}

		// 保存房间配置
		getRoomDatastore().save(entity);
		
		// 创建者
		Member member = new Member();
		member.setActive(DateUtil.currentTimeSeconds());
		member.setCreateTime(member.getActive());
		member.setModifyTime(0L);
		member.setNickname(user.getNickname());
		member.setRole(1);
		member.setRoomId(entity.getId());
		member.setSub(1);
		member.setTalkTime(0L);
		member.setCall(entity.getCall());
		member.setVideoMeetingNo(entity.getVideoMeetingNo());
		member.setUserId(user.getUserId());
		if(userKeys!=null)
			member.setChatKeyGroup(userKeys.getString(user.getUserId()+""));

		// 初始成员列表
		List<Member> memberList = Lists.newArrayList(member);

		//没有邀请群成员
		if(null == memberUserIdList ||memberUserIdList.isEmpty()){
			sendToChatNewMemberMessage(user.getUserId(),entity,member);

			/**
			 * 删除 用户加入的群组 jid  缓存
			 */
			SKBeanUtils.getRedisService().deleteUserRoomJidList(user.getUserId());
			if(0==SKBeanUtils.getUserManager().getOnlinestateByUserId(user.getUserId())) {
				SKBeanUtils.getRedisService().addRoomPushMember(entity.getJid(), user.getUserId());
			}
		}else if (null != memberUserIdList && !memberUserIdList.isEmpty()) {
			// 初始成员列表不为空
			Long currentTimeSeconds = DateUtil.currentTimeSeconds();
			ObjectId roomId = entity.getId();
			//添加群主
			memberUserIdList.add(user.getUserId());
			sendToChatNewMemberMessage(user.getUserId(),entity,member);

			Member _member =null;
			for (int userId : memberUserIdList) {
				User _user = getUserManager().getUser(userId);
				//群主在上面已经添加了
				if(userId!=member.getUserId()){
					//成员
						_member= new Member();
						_member.setActive(currentTimeSeconds);
						_member.setCreateTime(currentTimeSeconds);
						_member.setModifyTime(0L);
						_member.setNickname(_user.getNickname());
						_member.setRole(3);
						_member.setRoomId(roomId);
						_member.setSub(1);
						_member.setCall(entity.getCall());
						_member.setVideoMeetingNo(entity.getVideoMeetingNo());
						_member.setTalkTime(0L);
						_member.setUserId(_user.getUserId());
						if(userKeys!=null)
							_member.setChatKeyGroup(userKeys.getString(userId+""));
						memberList.add(_member);
					// 发送单聊通知到被邀请人， 群聊
					sendNewMemberMessage(user.getUserId(),entity,_member);
				}
				/**
				 * 删除 用户加入的群组 jid  缓存
				 */
				SKBeanUtils.getRedisService().deleteUserRoomJidList(userId);
				if(0==SKBeanUtils.getUserManager().getOnlinestateByUserId(userId)) {
					SKBeanUtils.getRedisService().addRoomPushMember(entity.getJid(), userId);
				}
			}
		}
		/**
		 * 分库分表保存
		 */
		List<DBObject> dbObjects = new ArrayList<DBObject>();
		memberList.forEach(memberss ->{
			DBObject dbObj = objectToDBObject(memberss);
			dbObjects.add(dbObj);
		});
		// 群成员分库分表保存
		getDBObjectCollection(entity.getId()).insertMany(dbObjects);
		// 群成员加入的群组jid 分库分表保存
		memberList.forEach(membersss ->{
			saveJidsByUserId(membersss.getUserId(), entity.getJid(),entity.getId());
		});


		updateUserSize(entity.getId(), memberList.size());
		
		// 用户加入的群组
		saveJidsByUserId(user.getUserId(),entity.getJid(),entity.getId());
		// 更新群组相关设置操作时间
		updateOfflineOperation(user.getUserId(), entity.getId(),null);

		//创建群头像

		String szJid = entity.getJid();
		String szUserIDList = "";
		int userCount = 0;
		for(Member _mem :  memberList)
		{
			//1.获取群前面9人用户头像
			szUserIDList += _mem.getUserId()+",";
			userCount++;
			if(userCount>=9) break;
		}
		//用户id,群ID 丢到第三方服务器去，免得频繁操作影响api服务器
		ThreadUtils.executeInThread(new createRoomImg(szUserIDList,szJid),1);
		//2.拉取用户头像，组合新群头像

		//3.上传新头像到服务器


		return entity;
	}

	/** @Description:更新群组相关设置操作时间
	* @param userId
	* @param roomId
	**/
	public void updateOfflineOperation(Integer userId,ObjectId roomId,String toUserIds){
		logger.info("userId is : {} ,  toUserIds is : {}",userId,toUserIds);
		long currentTime = DateUtil.currentTimeSeconds();
		Datastore datastore = SKBeanUtils.getDatastore();
		Query<OfflineOperation> query = datastore.createQuery(OfflineOperation.class).field("userId").equal(userId).field("friendId").equal(String.valueOf(roomId));
		if(null == query.get()){
			datastore.save(new OfflineOperation(userId, KConstants.MultipointLogin.TAG_ROOM, String.valueOf(roomId), currentTime));
		}else{
			UpdateOperations<OfflineOperation> ops = datastore.createUpdateOperations(OfflineOperation.class);
			ops.set("operationTime", currentTime);
			datastore.update(query, ops);
		}
		if(!StringUtil.isEmpty(toUserIds)){
			List<Integer> toUserIdList = StringUtil.getIntList(toUserIds, ",");
			toUserIdList.forEach(toUserId ->{
				Query<OfflineOperation> toUserQuery = datastore.createQuery(OfflineOperation.class).field("userId").equal(toUserId).field("friendId").equal(String.valueOf(roomId));
				if(null == toUserQuery.get()){
					datastore.save(new OfflineOperation(toUserId, KConstants.MultipointLogin.TAG_ROOM, String.valueOf(roomId), currentTime));
				}else{
					UpdateOperations<OfflineOperation> ops = datastore.createUpdateOperations(OfflineOperation.class);
					ops.set("operationTime", currentTime);
					datastore.update(toUserQuery, ops);
				}
			});
		}
	}

	public List<Integer> getRoomPushUserIdList(ObjectId roomId){
		Document query=new Document("roomId", roomId);
		query.append("offlineNoPushMsg", new Document(MongoOperator.NE, 1));
		List<Integer> memberIdList = new ArrayList<Integer>();
		MongoCursor<Integer> iterator = getCollection(roomId).distinct("userId", query, Integer.class).iterator();

		try {
			while (iterator.hasNext()) {
				Integer integer = (Integer) iterator.next();
				memberIdList.add(integer);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}
		return  memberIdList;
	}

	@Override
	public void delete(ObjectId roomId,Integer userId) {
		Query<Room> query = getRoomDatastore().createQuery(getEntityClass()).field("_id").equal(roomId);
		Room room =query.get();
		if(null==room){
			System.out.println("====> RoomManagerImplForIM > delete room is null ");
			return;
		}
		Member member = getMember(roomId, userId);

		List<Integer> userRoles = SKBeanUtils.getRoleManager().getUserRoles(userId);
		if(null != member){
			if(!userRoles.contains(5) && !userRoles.contains(6)){
				if(1 != member.getRole())
					throw new ServiceException(KConstants.ResultCode.NO_PERMISSION);
			}
		}else{
			if(!userRoles.contains(5) && !userRoles.contains(6))
				throw new ServiceException(KConstants.ResultCode.NO_PERMISSION);

		}
		String roomJid=room.getJid();
		if(room.getUserSize() >0){
			MessageBean messageBean = new MessageBean();
			messageBean.setFromUserId(room.getUserId() + "");
			messageBean.setFromUserName(getMemberNickname(roomId, room.getUserId()));
			messageBean.setType(KXMPPServiceImpl.DELETE_ROOM);
			messageBean.setObjectId(room.getJid());
			messageBean.setContent(room.getName());
			messageBean.setMessageId(StringUtil.randomUUID());
			// 发送单聊群聊
			sendChatGroupMsg(roomId, room.getJid(), messageBean);
		}
		
//		int createUserId=room.getUserId();
		ThreadUtil.executeInThread(new Callback() {
			@Override
			public void execute(Object obj) {
				getRoomDatastore().delete(query);

				List<Integer> memberIdList = getMemberIdList(roomId);
				for (Integer id : memberIdList) {
					// 维护用户加入群组 Jids 缓存
					SKBeanUtils.getRedisService().deleteUserRoomJidList(id);
					delJidsByUserId(id, roomJid);
				}
				/**
				 * 删除对应分库分表下的群成员
				 */
				Document document = new Document().append("roomId", roomId);
				getCollection(roomId).deleteMany(document);
				// 删除群组聊天记录
				SKBeanUtils.getImRoomDatastore().getDB().getCollection(DBConstants.RoomMsg_Collection_Prefix+roomJid).drop();

				//删除公告
				Query<Notice> notQuery = SKBeanUtils.getImRoomDatastore().createQuery(Room.Notice.class).field("roomId").equal(roomId);
				SKBeanUtils.getImRoomDatastore().delete(notQuery);
				
				//删除群组离线消息记录
				deleMucHistory(roomJid);

				// 删除 群共享的文件 和 群聊天消息的文件
				destroyRoomMsgFileAndShare(roomId, roomJid);

				// 删除群组相关的举报信息
				getUserManager().delReport(null, roomId.toString());


				User user = getUserManager().getUserFromDB(userId);
				destroyRoomToIM(user.getUserId()+"", user.getPassword(), roomJid);
				List<Member> memberList = getRedisServiceImpl().getMemberList(roomId.toString());

				// 维护群组、群成员缓存
				updateRoomInfoByRedis(roomId.toString());
				getRedisServiceImpl().deleteNoticeList(roomId.toString());
				deleteById(roomId);
			}
		});

	}
	
	/**
	* @Description: TODO(全员禁言)
	* @param @param roomId  群主ID
	* @param @param talkTime   禁言到期时间   0 取消禁言
	 */
	public void roomAllBanned(ObjectId roomId,long talkTime){
		ThreadUtil.executeInThread(new Callback() {
			@Override
			public void execute(Object obj) {
				/**
				 * 对应修改分库分表下成员数据
				 */
				Document query1 = new Document("roomId", roomId);
				getCollection(roomId).updateMany(query1, new Document(MongoOperator.SET,new Document("talkTime", talkTime)));
			}
		});
		
	}
	
	
	public synchronized JSONMessage update(User user,RoomVO roomVO,int isAdmin,int isConsole) {
		JSONMessage jsonMessage = JSONMessage.success();
		
		Query<Room> query = SKBeanUtils.getImRoomDatastore().createQuery(getEntityClass());
		query.filter("_id", roomVO.getRoomId());
		
		UpdateOperations<Room> operations =SKBeanUtils.getImRoomDatastore().createUpdateOperations(getEntityClass());

		Room room = getRoom(roomVO.getRoomId(),user.getUserId());
		if(0 == isConsole){
			if(null != room && room.getS() == -1)
				throw new ServiceException(KConstants.ResultCode.RoomIsLock);
		}
		if (!StringUtil.isEmpty(roomVO.getRoomName())&&(!room.getName().equals(roomVO.getRoomName()))) {
			UpdateGroupNickname(query,user, roomVO, isAdmin,room,operations);
			return jsonMessage;
		}
		/*全员禁言*/
		if(-2<roomVO.getTalkTime()){
			allBannedSpeak(query,user, roomVO, room, operations);
			return jsonMessage;
		}

		if (!StringUtil.isEmpty(roomVO.getDesc())) {
			operations.set("desc", roomVO.getDesc());
		}
		if (!StringUtil.isEmpty(roomVO.getSubject())) {
			operations.set("subject", roomVO.getSubject());
		}
		try {
			if (!StringUtil.isEmpty(roomVO.getNotice())) {
				if (getMember(room.getId(),ReqUtil.getUserId()).getRole() == 3) {
					return JSONMessage.failureByErrCode(KConstants.ResultCode.NO_PERMISSION, ReqUtil.getRequestLanguage());
				}
				String noticeId = newNotice(query,user, roomVO, isAdmin, room, operations);
				Map data=new HashedMap();
				data.put("noticeId",noticeId);
				return JSONMessage.success(data);
			}
		} catch (Exception e) {
				e.printStackTrace();
			}
		if(-1<roomVO.getShowRead()&&room.getShowRead()!=roomVO.getShowRead()){
			alreadyReadNums(query,user, roomVO, isAdmin, room, operations);
			return jsonMessage;
		}
		if(-1 != roomVO.getIsNeedVerify()){
			groupVerification(query,user, roomVO, isAdmin, room, operations);
			return jsonMessage;
		}
		if(-1!=roomVO.getIsLook()){
			roomIsPublic(query,user, roomVO, isAdmin, room, operations);
			return jsonMessage;
		}
		if(null != roomVO.getMaxUserSize() && roomVO.getMaxUserSize()>=0){
			if(roomVO.getMaxUserSize() < room.getUserSize())
				throw new ServiceException(KConstants.ResultCode.NotLowerGroupMember);
			int maxUserSize = SKBeanUtils.getAdminManager().getConfig().getMaxUserSize();
			if(roomVO.getMaxUserSize() > maxUserSize)
				throw new ServiceException(KConstants.ResultCode.RoomMemberAchieveMax);
			operations.set("maxUserSize",roomVO.getMaxUserSize());
		}
		// 锁定、取消锁定群组
		if(null != roomVO.getS() && 0 != roomVO.getS()){
			roomIsLocking(query, user, roomVO, isAdmin, room, operations);
			return jsonMessage;
		}
			
		if(-1!=roomVO.getShowMember()){
			showMember(query,user, roomVO, isAdmin, room, operations);
			return jsonMessage;
		}
		if(-1!=roomVO.getAllowSendCard()){
			roomAllowSendCard(query,user, roomVO, isAdmin, room, operations);
			return jsonMessage;
		}
		
		if(-1!=roomVO.getAllowInviteFriend()){
			roomAllowInviteFriend(query,user, roomVO, room, operations);
			return jsonMessage;
		}
		
		if(-1!=roomVO.getAllowUploadFile()){
			roomAllowUploadFile(query,user, roomVO, room, operations);
			return jsonMessage;
		}
		
		if(-1!=roomVO.getAllowConference()){
			roomAllowConference(query,user, roomVO, room, operations);
			return jsonMessage;
		}
		
		if(-1!=roomVO.getAllowSpeakCourse()){
			roomAllowSpeakCourse(query,user, roomVO, room, operations);
			return jsonMessage;
		}
	
		if(-1!=roomVO.getAllowHostUpdate())
			operations.set("allowHostUpdate",roomVO.getAllowHostUpdate());
		
		if(-2!=roomVO.getChatRecordTimeOut())// 聊天记录超时
			ChatRecordTimeOut(query,user,roomVO,room,operations);

		
		if(-1!=roomVO.getIsAttritionNotice())
			operations.set("isAttritionNotice",roomVO.getIsAttritionNotice());

		operations.set("modifyTime", DateUtil.currentTimeSeconds());
		

		synchronized (query) {
			getRoomDatastore().update(query, operations);
		}
		// 维护群组相关缓存
		getRedisServiceImpl().deleteRoom(roomVO.getRoomId().toString());
		return jsonMessage;
	}
	
	public void updateEncryptType(Room room,int encryptType){
		updateAttribute(room.getId(),"encryptType",encryptType);
		SKBeanUtils.getRedisService().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		try {
			// IMPORTANT 1-2、改房间名推送-已改
			messageBean.setFromUserId(room.getUserId() + "");
			messageBean.setFromUserName(getUserManager().getNickName(room.getUserId()));
			messageBean.setType(KXMPPServiceImpl.ModifyEncryptType);
			messageBean.setObjectId(room.getJid());
			messageBean.setContent(encryptType);
			messageBean.setMessageId(StringUtil.randomUUID());
			messageBean.setToUserId(room.getJid());
			// 发送群聊
			sendGroupMsg(room.getJid(), messageBean);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}

	}
	public void resetGroupChatKey(Room room,final JSONObject jsonGroupKeys){

		ThreadUtil.executeInThread(obj -> {
			try {
				final DBCollection dbCollection = getRoomDatastore().getCollection(Room.Member.class);

				getRoomDatastore().getDB().getCollection(DBConstants.RoomMsg_Collection_Prefix+room.getJid()).drop();
				MessageBean messageBean = new MessageBean();
				messageBean.setFromUserId(room.getUserId() + "");
				messageBean.setFromUserName(getUserManager().getNickName(room.getUserId()));
				messageBean.setType(806);
				messageBean.setObjectId(room.getJid());
				messageBean.setToUserId(room.getJid());
				messageBean.setContent(room.getName());
				messageBean.setMessageId(StringUtil.randomUUID());
				sendGroupMsg(room.getJid(),messageBean);
                jsonGroupKeys.entrySet().stream().forEach( entny ->{
                    DBObject query = new BasicDBObject().append("roomId", room.getId()).append("userId",Integer.valueOf(entny.getKey()));
                    BasicDBObject values=new BasicDBObject(com.shiku.common.core.MongoOperator.SET,new BasicDBObject("chatKeyGroup",entny.getValue()));
                    dbCollection.update(query,values);
                });
			}catch (Exception e){
				e.printStackTrace();
			}

		});




	}
	public void updateGroupChatKey(Room room,int userId,final String key){

			try {
				final MongoCollection<Document> dbCollection = getCollection(userId);
				MessageBean messageBean = new MessageBean();
				messageBean.setFromUserId(room.getUserId() + "");
				messageBean.setFromUserName(getUserManager().getNickName(room.getUserId()));
				messageBean.setType(806);
				messageBean.setObjectId(room.getJid());
				messageBean.setToUserId(room.getJid());
				messageBean.setContent(room.getName());
				messageBean.setMessageId(StringUtil.randomUUID());
				sendGroupMsg(room.getJid(),messageBean);
				Document query = new Document().append("roomId", room.getId()).append("userId",userId);
				Document values=new Document(com.shiku.common.core.MongoOperator.SET,new Document("chatKeyGroup",key));
				dbCollection.updateOne(query,values);
			}catch (Exception e){
				e.printStackTrace();
			}





	}

	/** @Description:维护群组、群成员 缓存
	* @param roomId
	**/ 
	protected void updateRoomInfoByRedis(String roomId){
		getRedisServiceImpl().deleteRoom(roomId);
		getRedisServiceImpl().deleteMemberList(roomId);
	}
	
	// 修改群昵称
	public synchronized void UpdateGroupNickname(Query<Room> query,User user,RoomVO roomVO,int isAdmin,Room room,UpdateOperations<Room> operations) {
		
		operations.set("name", roomVO.getRoomName());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		if (1 == isAdmin) {
			// IMPORTANT 1-2、改房间名推送-已改
			messageBean.setFromUserId(user.getUserId() + "");
			messageBean.setFromUserName(("10005".equals(user.getUserId().toString())?"后台管理员":getMemberNickname(room.getId(), user.getUserId())));
			messageBean.setType(KXMPPServiceImpl.CHANGE_ROOM_NAME);
			messageBean.setObjectId(room.getJid());
			messageBean.setContent(roomVO.getRoomName());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
		
	}
	
	// 全员禁言
	public void allBannedSpeak(Query<Room> query,User user,RoomVO roomVO,Room room,UpdateOperations<Room> operations){
		operations.set("talkTime", roomVO.getTalkTime());
		updateGroup(query, operations);
		roomAllBanned(roomVO.getRoomId(), roomVO.getTalkTime());
		/**
		 * 维护群组、群成员缓存
		 */
		updateRoomInfoByRedis(room.getId().toString());
		MessageBean messageBean=new MessageBean();
		messageBean.setType(KXMPPServiceImpl.RoomAllBanned);
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
		messageBean.setContent(String.valueOf(roomVO.getTalkTime()));
		messageBean.setObjectId(room.getJid());
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送群聊通知
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 新公告
	public String newNotice(Query<Room> query,User user,RoomVO roomVO,int isAdmin,Room room,UpdateOperations<Room> operations){
		Notice notice = new Notice(new ObjectId(),roomVO.getRoomId(),roomVO.getNotice(),user.getUserId(),user.getNickname());
		// 更新最新公告
		operations.set("notice", notice);
		updateGroup(query, operations);
		// 新增历史公告记录
		getRoomDatastore().save(notice);
		/**
		 * 维护公告
		 */
		getRedisServiceImpl().deleteNoticeList(room.getId());
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		if (1 == isAdmin) {
			// IMPORTANT 1-5、改公告推送-已改
			messageBean.setFromUserId(user.getUserId() + "");
			messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
			messageBean.setType(KXMPPServiceImpl.NEW_NOTICE);
			messageBean.setObjectId(room.getJid());
			messageBean.setContent(roomVO.getNotice());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
		return notice.getId().toString();
	}
	
	// 显示已读人数
	public void alreadyReadNums(Query<Room> query,User user,RoomVO roomVO,int isAdmin,Room room,UpdateOperations<Room> operations){
		operations.set("showRead", roomVO.getShowRead());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean=new MessageBean();
		if(1==isAdmin){
			messageBean.setType(KXMPPServiceImpl.SHOWREAD);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
			messageBean.setContent(String.valueOf(roomVO.getShowRead()));
			messageBean.setObjectId(room.getJid());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 群组验证
	public void groupVerification(Query<Room> query,User user,RoomVO roomVO,int isAdmin,Room room,UpdateOperations<Room> operations){
		operations.set("isNeedVerify",roomVO.getIsNeedVerify());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean=new MessageBean();
		if(1==isAdmin){
			messageBean.setType(KXMPPServiceImpl.RoomNeedVerify);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
			messageBean.setContent(String.valueOf(roomVO.getIsNeedVerify()));
			messageBean.setObjectId(room.getJid());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 是否公开群组
	public void roomIsPublic(Query<Room> query,User user,RoomVO roomVO,int isAdmin,Room room,UpdateOperations<Room> operations){
		operations.set("isLook",roomVO.getIsLook());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean=new MessageBean();
		if(1==isAdmin){
			messageBean.setType(KXMPPServiceImpl.RoomIsPublic);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
			messageBean.setContent(String.valueOf(roomVO.getIsLook()));
			messageBean.setObjectId(room.getJid());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 群组是否被锁定
	public void roomIsLocking(Query<Room> query,User user,RoomVO roomVO,int isAdmin,Room room,UpdateOperations<Room> operations){
		operations.set("s",roomVO.getS());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean=new MessageBean();
		if(1==isAdmin){
			messageBean.setType(KXMPPServiceImpl.consoleProhibitRoom);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
			messageBean.setContent(roomVO.getS());
			messageBean.setObjectId(room.getJid());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendChatGroupMsg(roomVO.getRoomId(), room.getJid(), messageBean);
	}
	
	
	// 是否允许发送名片
	public void roomAllowSendCard(Query<Room> query,User user,RoomVO roomVO,int isAdmin,Room room,UpdateOperations<Room> operations){
		operations.set("allowSendCard",roomVO.getAllowSendCard());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean=new MessageBean();
		if(1==isAdmin){
			messageBean.setType(KXMPPServiceImpl.RoomAllowSendCard);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
			messageBean.setContent(String.valueOf(roomVO.getAllowSendCard()));
			messageBean.setObjectId(room.getJid());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 普通成员 是否可以看到 群组内的成员
	public void showMember(Query<Room> query,User user, RoomVO roomVO, int isAdmin, Room room, UpdateOperations<Room> operations) {
		operations.set("showMember", roomVO.getShowMember());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		if (1 == isAdmin) {
			messageBean.setType(KXMPPServiceImpl.RoomShowMember);
			messageBean.setFromUserId(user.getUserId().toString());
			messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
			messageBean.setContent(String.valueOf(roomVO.getShowMember()));
			messageBean.setObjectId(room.getJid());
			messageBean.setMessageId(StringUtil.randomUUID());
		}
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 是否允许群成员邀请好友
	public void roomAllowInviteFriend(Query<Room> query,User user, RoomVO roomVO, Room room, UpdateOperations<Room> operations) {
		operations.set("allowInviteFriend", roomVO.getAllowInviteFriend());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		messageBean.setType(KXMPPServiceImpl.RoomAllowInviteFriend);
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
		messageBean.setContent(String.valueOf(roomVO.getAllowInviteFriend()));
		messageBean.setObjectId(room.getJid());
		messageBean.setMessageId(UUID.randomUUID().toString());
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 是否允许群成员上传文件
	public void roomAllowUploadFile(Query<Room> query,User user, RoomVO roomVO, Room room, UpdateOperations<Room> operations) {
		operations.set("allowUploadFile", roomVO.getAllowUploadFile());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		messageBean.setType(KXMPPServiceImpl.RoomAllowUploadFile);
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
		messageBean.setContent(String.valueOf(roomVO.getAllowUploadFile()));
		messageBean.setObjectId(room.getJid());
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 群组允许成员召开会议
	public void roomAllowConference(Query<Room> query,User user, RoomVO roomVO, Room room, UpdateOperations<Room> operations) {
		operations.set("allowConference", roomVO.getAllowConference());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		messageBean.setType(KXMPPServiceImpl.RoomAllowConference);
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
		messageBean.setContent(String.valueOf(roomVO.getAllowConference()));
		messageBean.setObjectId(room.getJid());
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	//  群组允许成员开启讲课
	public void roomAllowSpeakCourse(Query<Room> query,User user, RoomVO roomVO, Room room, UpdateOperations<Room> operations) {
		operations.set("allowSpeakCourse", roomVO.getAllowSpeakCourse());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		messageBean.setType(KXMPPServiceImpl.RoomAllowSpeakCourse);
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
		messageBean.setContent(String.valueOf(roomVO.getAllowSpeakCourse()));
		messageBean.setObjectId(room.getJid());
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
	}
	
	// 聊天记录超时设置 通知
	public void ChatRecordTimeOut(Query<Room> query,User user,RoomVO roomVO,Room room,UpdateOperations<Room> operations){
		operations.set("chatRecordTimeOut",roomVO.getChatRecordTimeOut());
		updateGroup(query, operations);
		/**
		 * 维护群组缓存
		 */
		getRedisServiceImpl().deleteRoom(room.getId().toString());
		MessageBean messageBean = new MessageBean();
		messageBean.setType(KXMPPServiceImpl.ChatRecordTimeOut);
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(room.getId(), user.getUserId()));
		messageBean.setContent(String.valueOf(roomVO.getChatRecordTimeOut()));
		messageBean.setObjectId(room.getJid());
		messageBean.setMessageId(StringUtil.randomUUID());
		
		// 发送群聊
		sendGroupMsg(room.getJid(), messageBean);
		
	}
	
	public synchronized void updateGroup(Query<Room> query,UpdateOperations<Room> operations){
		getRoomDatastore().update(query, operations);
	}
	
	// 单聊通知某个人
	public void sendGroupOne(Integer userIds,MessageBean messageBean){
		try {
			messageBean.setMsgType(0);
			KXMPPServiceImpl.getInstance().send(messageBean);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 发送群聊通知
	public void sendGroupMsg(String jid,MessageBean messageBean){
		try {
			KXMPPServiceImpl.getInstance().sendMsgToGroupByJid(jid,messageBean);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 发送单聊通知某个人 ,且 发送群聊通知
	public void sendChatToOneGroupMsg(Integer userIds, String jid,MessageBean messageBean){
		try {
			// 发送单聊
			messageBean.setMsgType(0);
			if(StringUtil.isEmpty(messageBean.getMessageId()))
				messageBean.setMessageId(StringUtil.randomUUID());
			KXMPPServiceImpl.getInstance().send(messageBean);
			// 发送群聊
			ThreadUtil.executeInThread(new Callback() {
				
				@Override
				public void execute(Object obj) {
					try {
						KXMPPServiceImpl.getInstance().sendMsgToGroupByJid(jid, messageBean);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	// 发送单聊通知群组所有人 ,且 发送群聊通知
	public void sendChatGroupMsg(ObjectId roomId,String jid,MessageBean messageBean){
		try {
			// 发送单聊
			messageBean.setMsgType(0);
			messageBean.setMessageId(StringUtil.randomUUID());
			KXMPPServiceImpl.getInstance().send(messageBean,getMemberIdList(roomId));
			// 发送群聊
			ThreadUtil.executeInThread(new Callback() {
				
				@Override
				public void execute(Object obj) {
					try {
						KXMPPServiceImpl.getInstance().sendMsgToGroupByJid(jid, messageBean);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
			});
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	
	/**
	* @Description: TODO(群主 转让)
	* @param @param roomId  群主ID
	* @param @param toUserId   新群主 用户ID   必须 是 群内成员
	 */
	public Room transfer(Room room,Integer toUserId){
		
		String nickName = getUserManager().getNickName(toUserId);
		Query<Room> roomQuery = getRoomDatastore().createQuery(getEntityClass()).filter("_id", room.getId());
		UpdateOperations<Room> roomOps = getRoomDatastore().createUpdateOperations(getEntityClass());
		roomOps.set("userId", toUserId);
		roomOps.set("nickname", nickName);
		getRoomDatastore().update(roomQuery, roomOps);

		
		/**
		 * 修改分库分表下对应群成员数据
		 */
		MongoCollection collection = getCollection(room.getId());
		collection.updateOne(new Document("roomId",room.getId()).append("userId", room.getUserId()), new Document(MongoOperator.SET,new Document("role",3)));


		collection.updateOne(new Document("roomId",room.getId()).append("userId", toUserId), new Document(MongoOperator.SET,new Document("role",1)));
		// 更新群组、群成员相关缓存
		updateRoomInfoByRedis(room.getId().toString());
		MessageBean message=new MessageBean();
		message.setType(KXMPPServiceImpl.RoomTransfer);
		message.setFromUserId(room.getUserId().toString());
		message.setFromUserName(getMemberNickname(room.getId(), room.getUserId()));
		message.setObjectId(room.getJid());
		message.setToUserId(toUserId.toString());
		message.setToUserName(getUserManager().getNickName(toUserId));
		message.setMessageId(StringUtil.randomUUID());
		// 发送单聊通知被转让的人、群聊通知
		sendChatToOneGroupMsg(toUserId, room.getJid(), message);
		return get(room.getId());
	}
	
	
	@Override
	public Room get(ObjectId roomId,Integer pageIndex,Integer pageSize) {
		// redis room 不包含 members noties
		Room redisRoom = SKBeanUtils.getRedisService().queryRoom(roomId);
		if(null != redisRoom){
			if(-1 == redisRoom.getS())
				throw new ServiceException(KConstants.ResultCode.RoomIsLock);
			Room specialRoom = specialHandleByRoom(redisRoom, roomId,pageIndex,pageSize);
			return specialRoom;
		}else{
			Room room = getRoomDatastore().createQuery(getEntityClass()).field("_id").equal(roomId).get();
			if(null != room && -1 == room.getS())
				throw new ServiceException(KConstants.ResultCode.RoomIsLock);
			if(null==room)
				throw new ServiceException(KConstants.ResultCode.NotRoom);
			Room specialRoom = specialHandleByRoom(room, roomId,pageIndex,pageSize);
			return specialRoom;
		}
	}

	public Room getRoomByJid(String roomJid) {
		return getRoomDatastore().createQuery(getEntityClass()).field("jid").equal(roomJid).get();
	}

	/** @Description: 房间相关特殊处理操作
	* @param room
	* @param roomId
	* @return
	**/
	public Room specialHandleByRoom(Room room,ObjectId roomId,Integer pageIndex,Integer pageSize){
		// 特殊身份处理
		Member member = SKBeanUtils.getRoomManagerImplForIM().getMember(roomId, ReqUtil.getUserId());
		if(null == member){
			// 主动加群（二维码扫描），该用户不再群组内，需要members
			Room joinRoom = getRoom(roomId);
//			List<Member> members = getMembers(roomId,pageIndex,pageSize);
			List<Member> members = getHeadMemberListByPageImpls(roomId, pageSize,0);
			joinRoom.setMembers(members);
			return joinRoom;
		}
		int role = member.getRole();
		List<Member> members = new ArrayList<>();
		// 监护人和隐身人不能互看  保证每次都有自己
		if(1 != member.getRole()){
			if(role > 1 && role < 4){

				/**
				 * 查询分库分表的群成员
				 */
				long count = getCollection(roomId).count(new Document("roomId",roomId).append("role", new Document(MongoOperator.LT,4)));
				MongoCursor<Document> iterator = getCollection(roomId).find(new Document("roomId",roomId).append("role", new Document(MongoOperator.LT,4))).iterator();
				try {
					Member docMember=null;
					while(iterator.hasNext()){
						Document document = iterator.next();
						try {
							docMember = DocumentToJavaBean.setFieldValue(new Member(), document);
							 if(null!=docMember)
							 {
								 if(!document.containsKey("nicknameModifyTime"))
									{
									 	docMember.setNickname(SKBeanUtils.getUserManager().getNickName(docMember.getUserId()));
									}
									members.add(docMember);
							}
							
						} catch (Exception e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}finally {
					iterator.close();
				}

			}else if(role == 4 || role == 5){
				// 隐身人、监护人

				/**
				 * 查询分库分表的群成员
				 */
				List<Document> documents = new ArrayList<Document>();
				documents.add(new Document("role",new Document(MongoOperator.LT,4)));
				documents.add(new Document("userId",ReqUtil.getUserId()));
				Document query = new Document("roomId",roomId).append(MongoOperator.OR, documents);
				FindIterable<Document> find = getCollection(roomId).find(query);
				MongoCursor<Document> iterator = find.iterator();

				try {
					while(iterator.hasNext()){
						Member docMember = new Member();
						Document document = iterator.next();
						docMember = (Member) DocumentToJavaBean.setFieldValue(docMember, document);
						if(null!=docMember)
						 {
							 if(!document.containsKey("nicknameModifyTime"))
								{
								 	docMember.setNickname(SKBeanUtils.getUserManager().getNickName(docMember.getUserId()));
								}
								members.add(docMember);
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}finally {
					iterator.close();
				}
			}
			room.setUserSize(members.size());
			room.setMembers(members);
		}else {
			List<Member> membersList = getHeadMemberListByPageImpls(roomId, pageSize,member.getRole());
			room.setMembers(membersList);
		}
		// 群公告
		List<Notice> noticesCache = getRedisServiceImpl().getNoticeList(roomId);
		if(null != noticesCache && noticesCache.size() > 0){
			room.setNotices(noticesCache);
		}else{
			List<Notice> noticesDB = getRoomDatastore().createQuery(Room.Notice.class).field("roomId").equal(roomId).order("-time").asList();
			room.setNotices(noticesDB);
			/**
			 * 维护群公告列表缓存
			 */
			getRedisServiceImpl().saveNoticeList(roomId, noticesDB);
		}
		return room;
	}

	public List<Member> getMembers(ObjectId roomId){
		List<Member> members = null;
		// 群成员
		List<Member> memberList = getRedisServiceImpl().getMemberList(roomId.toString());
		if(null != memberList && memberList.size() > 0)
			members = memberList;
		else{
			List<Member> membersDB = getMemberList(roomId, null);
			members = membersDB;
			/**
			 * 维护群成员列表缓存
			 */
			getRedisServiceImpl().saveMemberList(roomId.toString(), membersDB);
		}
		return members;
	}
	/** @Description:room/get 和 joinTime 为0时返回群成员 列表
	 * // 补全问题 ： 例如 ：pageSize = 100 。  第一种情况 小于pageSize{ 群组 + 管理员 = 80人   返回 80+20普通群成员}
	 *  第二种情况 大于等于pageSize{ 群组 + 管理员 = 120人   返回 120人 + 1名最先加群的普通群成员主要拿到createTime}
	* @param roomId
	* @param pageSize
	* @return
	**/
	@SuppressWarnings("deprecation")
	public List<Member> getHeadMemberListByPageImpls(ObjectId roomId,Integer pageSize,int role){

		List<Member> members = getAdministrationMemberList(roomId);
		MongoCollection<Document> collection = getCollection(roomId);
		int adminSize = members.size();
		Document query=new Document("roomId", roomId);
		query.append("role", new Document("$gt", 2));
		if(KConstants.Room_Role.CREATOR != role){
			query.append("role",new Document("$ne",4));
		}
		if(adminSize < pageSize){
			// 补全pageSize

			MongoCursor<Document> iterator = collection.find(query).sort(new Document("createTime", 1)).limit(pageSize - adminSize).iterator();
			Document document=null;
			Member member=null;

			try {
				while (iterator.hasNext()) {
					 document = (Document) iterator.next();
					 member= (Member) DocumentToJavaBean.setFieldValue(new Member(), document);
					 if(null!=member)
					 {
						 if(!document.containsKey("nicknameModifyTime"))
							{
								member.setNickname(SKBeanUtils.getUserManager().getNickName(member.getUserId()));
							}
						 User _user = SKBeanUtils.getUserManager().getUser(member.getUserId());
						 if(_user!= null) member.setAccounts(_user.getAccount());
						 members.add(member);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				iterator.close();
			}
		}else{
			Document document = collection.find(query).sort(new Document("createTime", 1)).first();
			Member member=null;
			if(null!=document) {
				 member=new Member();
				member= (Member) DocumentToJavaBean.setFieldValue(member, document);
				 if(null!=member)
				 {
					 if(!document.containsKey("nicknameModifyTime"))
					 {
					 	member.setNickname(SKBeanUtils.getUserManager().getNickName(member.getUserId()));
					 }
					 User _user = SKBeanUtils.getUserManager().getUser(member.getUserId());
					 if(_user!= null) member.setAccounts(_user.getAccount());
					 members.add(member);
				}
			}
		}
		return members;

	}
	/** 特殊身份对应的房间信息
	 * @param role
	 * @param room
	 * @param
	 * @param roomId
	 * @return
	 */
	private Room specialRole(int role,Room room,ObjectId roomId){
		/**
		 * 分库分表下
		 */
		MongoCollection collection = getCollection(roomId);
		List<Member> members = new ArrayList<Member>();
		if(role > 1 && role < 4){
			/**
			 * 查询分库分表的群成员
			 */
			long count = collection.count(new Document("roomId",roomId).append("role", new Document(MongoOperator.LT,4)));
			MongoCursor<Document> iterator = collection.find(new Document("roomId",roomId).append("role", new Document(MongoOperator.LT,4))).iterator();

			try {
				Member docMember=null;
				while(iterator.hasNext()){

					Document document = iterator.next();
					docMember = DocumentToJavaBean.setFieldValue(new Member(), document);
					if(null!=docMember)
						members.add(docMember);

				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				iterator.close();
			}
			room.setUserSize((int) (room.getUserSize()-count));
		}else if(role == 4){

			/**
			 * 查询分库分表的群成员
			 */
			MongoCursor<Document> iterator = collection.find(new Document("roomId",roomId).append("role", new Document(MongoOperator.LTE,4))).iterator();
			try {
				while(iterator.hasNext()){
					Member docMember = new Member();
					Document document = iterator.next();
					docMember = (Member) DocumentToJavaBean.setFieldValue(docMember, document);
					members.add(docMember);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				iterator.close();
			}

			room.setUserSize(members.size());
		}else if(role == 5){
			/**
			 * 查询分库分表的群成员
			 */
			MongoCursor<Document> iterator = collection.find(new Document("roomId",roomId).append("role", new Document(MongoOperator.LT,5)).append("role", new Document(MongoOperator.NE,5))).iterator();

			try {
				while(iterator.hasNext()){
					Member docMember = new Member();
					Document document = iterator.next();
					docMember = (Member) DocumentToJavaBean.setFieldValue(docMember, document);
					members.add(docMember);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				iterator.close();
			}
			room.setUserSize(members.size());
		}
		room.setMembers(members);
		return room;
	}

	/** @Description:群成员分页
	* @param roomId
	* @param joinTime
	* @param pageSize
	* @return
	**/
	@SuppressWarnings("deprecation")
	public List<Member> getMemberListByPageImpl(ObjectId roomId,long joinTime,Integer pageSize,int role){

		if(0 == joinTime)
			return getHeadMemberListByPageImpls(roomId, pageSize,role);
		Document query=new Document("roomId", roomId).append("role", new Document("$gt", 2)).append("createTime", new Document("$gte", joinTime));
		if(KConstants.Room_Role.CREATOR != role){
			query.append("role",new Document("$ne",4));
		}
		 MongoCursor<Document> iterator = getCollection(roomId).find(query).sort(new Document("createTime", 1)).limit(pageSize).iterator();
		Document document=null;
		Member member=null;
		List<Member> members=new ArrayList<Member>();

		try {
			while (iterator.hasNext()) {
				 document =iterator.next();
				 member= DocumentToJavaBean.setFieldValue(new Member(), document);
				if(null!=member) {
					User _user = SKBeanUtils.getUserManager().getUser(member.getUserId());
					if(_user!= null){
						logger.info("[ww]:member.getUserId()"+member.getUserId()+","+_user.getAccount());
						member.setAccounts(_user.getAccount());
					}
					logger.info("[ww]:member=add");
					members.add(member);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}
		return members;
	}
	public Room consoleGetRoom(ObjectId roomId) {
		Room room = getRoomDatastore().createQuery(getEntityClass()).field("_id").equal(roomId).get();

		if (null != room) {
			List<Member> members = getRoomDatastore().createQuery(Room.Member.class).field("roomId").equal(roomId).order("createTime").order("role").asList();
			List<Notice> notices = getRoomDatastore().createQuery(Room.Notice.class).field("roomId").equal(roomId).order("-time").asList();

			room.setMembers(members);
			room.setNotices(notices);
			if(0==room.getUserSize()){
				room.setUserSize(members.size());
				DBObject q = new BasicDBObject("_id", roomId);
				DBObject o = new BasicDBObject("$set", new BasicDBObject("userSize", members.size()));
				getRoomDatastore().getCollection(getEntityClass()).update(q, o);
			}
		}
		return room;
	}
	
	
	/**
	* @Description: TODO(只获取群组详情，群主和管理员信息，不获取普通群成员列表和公告列表,)
	* @param @param roomId
	* @param @return    参数
	 */
	public Room getRoom(ObjectId roomId){
		return getRoom(roomId,ReqUtil.getUserId());
	}
	/**
	* @Description: TODO(只获取群组详情，群主和管理员信息，不获取普通群成员列表和公告列表,)
	* @param @param roomId
	* @param @return    参数
	 */
	public Room getRoom(ObjectId roomId,int userId){
		Room room = null;
		Room roomCache = getRedisServiceImpl().queryRoom(roomId);
		if(null != roomCache){
			room = roomCache;
		}else{
			Room roomDB = getRoomDatastore().createQuery(getEntityClass()).field("_id").equal(roomId).get();
			if(null == roomDB)
				throw new ServiceException(KConstants.ResultCode.NotRoom);
			room = roomDB;
			/**
			 * 缓存 房间
			 */
			getRedisServiceImpl().saveRoom(room);
		}
		// 群组和管理员信息
		room.setMembers(getAdministrationMemberList(roomId));
		int userRole = SKBeanUtils.getRoleManager().getUserRoleByUserId(userId);
		Member member = null;
		int role = 0;
		member = getMember(roomId, userId);
		// 面对面建群，用户不在群组中处理
		if(null == member)
			return room;
		role = member.getRole();
		// 后台管理中获取群组详情
		if(KConstants.Admin_Role.ADMIN != userRole && KConstants.Admin_Role.SUPER_ADMIN != userRole){
			member = getMember(roomId, userId);
			if(null == member)
				throw new ServiceException(KConstants.ResultCode.MemberNotInGroup);
			role = member.getRole();
		}
//		Query<Member> memberQuery = getDatastore().createQuery(Member.class).field("roomId").equal(roomId);
		if(KConstants.Room_Role.CREATOR < role && role < KConstants.Room_Role.INVISIBLE){
//			long invisibleCustodyCount = memberQuery.field("role").greaterThanOrEq(KConstants.Room_Role.INVISIBLE).count();
			long invisibleCustodyCount = getCollection(roomId).count(new Document("roomId",roomId).append("role",new Document(MongoOperator.GTE,KConstants.Room_Role.INVISIBLE)));
			int userSize = (int) (room.getUserSize() - invisibleCustodyCount);
			room.setUserSize(userSize);
		}else if(KConstants.Room_Role.INVISIBLE == role || KConstants.Room_Role.GUARDIAN == role){
//			memberQuery.or(memberQuery.criteria("role").lessThan(KConstants.Room_Role.INVISIBLE),memberQuery.criteria("userId").equal(userId));
//			long userCount = memberQuery.count();
			List<Document> documents = new ArrayList<>();
			documents.add(new Document("role",new Document(MongoOperator.LT,KConstants.Room_Role.INVISIBLE)));
			documents.add(new Document("userId",userId));
			long userCount = getCollection(roomId).count(new Document("roomId",roomId).append(MongoOperator.OR,documents));
			room.setUserSize((int) userCount);
		}
		return room;
	}
	public Integer getCreateUserId(ObjectId roomId){
		return (Integer) queryOneField("userId", new BasicDBObject("_id", roomId));
	}
	public ObjectId getRoomId(String jid) {
		return (ObjectId) queryOneField("_id", new BasicDBObject("jid", jid));
	}
	public String queryRoomJid(ObjectId roomId) {
		return (String) queryOneFieldById("jid",roomId);
	}
	public Integer queryRoomStatus(ObjectId roomId) {
		return (Integer) queryOneFieldById("s",roomId);
	}
	public String getRoomName(String jid) {
		return (String) queryOneField("name", new BasicDBObject("jid", jid));
	}
	public String getRoomName(ObjectId roomId) {
		return (String) queryOneField("name", new BasicDBObject("_id", roomId));
	}
	// 房间状态
	public Integer getRoomStatus(ObjectId roomId) {
		return (Integer) queryOneField("s", new BasicDBObject("_id", roomId));
	}
	@Override
	public List<Room> selectList(int pageIndex, int pageSize, String roomName) {
		Query<Room> q = getRoomDatastore().createQuery(getEntityClass());
		if (!StringUtil.isEmpty(roomName)){
			//q.field("name").contains(roomName);
			q.or(q.criteria("name").containsIgnoreCase(roomName),
					q.criteria("desc").containsIgnoreCase(roomName));
		}
		q.filter("isLook", 0);
		q.field("isSecretGroup").notEqual(1);
		List<Room> roomList = q.offset(pageIndex * pageSize).limit(pageSize).order("-_id").asList();
		return roomList;
	}



	/**
	* @Description: TODO(查询用户加入的所有群的jid)
	* @param @param userId
	* @param @return    参数
	 */
	public List<String> queryUserRoomsJidList(int userId){
		List<String> jids = new ArrayList<String>();
		MongoCursor<String> iterator = getCollection(userId).distinct("jid", new Document("userId",userId), String.class).iterator();

		try {
			while(iterator.hasNext()){
				String jid = iterator.next();
				if(null!=jid)
					jids.add(jid);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}
		return jids;
	}

	/**
	 * 查询用户开启免打扰的  群组Jid 列表
	 * @param userId
	 * @return
	 */
	public List<String> queryUserNoPushJidList(int userId){
		 Document query = new Document("userId",userId).append("offlineNoPushMsg", 1);
		List<String> jids = new ArrayList<String>();
		MongoCursor<String> iterator = getCollection(userId).distinct("jid",query, String.class).iterator();

		try {
			while(iterator.hasNext()){
				String jid = iterator.next();
				if(null!=jid)
					jids.add(jid);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}
		return jids;
	}
	
	/**
	* @Description: TODO(查询用户加入的所有群的roomId)
	* @param @param userId
	* @param @return    参数
	 */
	public List<ObjectId> queryUserRoomsIdList(int userId){

		return getRoomIdList(userId);
	}

	@SuppressWarnings({ "deprecation", "unchecked" })
	@Override
	public Object selectHistoryList(int userId, int type, int pageIndex, int pageSize) {
		/**
		 * user ====> roomIds
		 */
		List<ObjectId> roomIds=queryUserRoomsIdList(userId);

		if(roomIds.isEmpty())
			return null;
		Query<Room> limit = getRoomDatastore().createQuery(getEntityClass()).field("_id").in(roomIds).field("s").equal(1).order("-_id").offset(pageIndex * pageSize).limit(pageSize);
		List<Room> historyList = limit.asList();
		historyList.forEach(room -> {
			Member member = getMember(room.getId(), userId);
			room.setMember(member);
		});

		return historyList;
	}

	/* (non-Javadoc)
	 * @see cn.xyz.mianshi.service.RoomManager#deleteMember(cn.xyz.mianshi.vo.User, org.bson.types.ObjectId, int)
	 */
	@Override
	public void deleteMember(User user, ObjectId roomId, int userId) {
		Room room = getRoom(roomId,user.getUserId());
		if(-1 == room.getS()){
			throw new ServiceException("该群已经被锁定！");
		}
		Member roomMember =null;
		if(null!=user)
			roomMember=getMember(roomId, user.getUserId());
		Member member = getMember(roomId, userId);
		if(member == null)
			throw new ServiceException(KConstants.ResultCode.MemberNotInGroup);
		// 处理解散群组
		if(room.getUserId().equals(userId)){
			delete(roomId, userId);
			return;
		}
        if(null == roomMember) {
            // 处理后台管理员
            // 后台管理员
            Query<Role> roleQuery = SKBeanUtils.getDatastore().createQuery(Role.class).field("userId").equal(user.getUserId());
            if (null != roleQuery.get()) {
                if (5 == roleQuery.get().getRole() || 6 == roleQuery.get().getRole()) {
                    if (-1 == roleQuery.get().getStatus())
						throw new ServiceException(KConstants.ResultCode.BackAdminStatusError);
                    if (room.getUserId().equals(userId)) {
						throw new ServiceException(KConstants.ResultCode.NotRemoveOwner);
                    }
                }
            }
        }else if(!user.getUserId().equals(userId)){
            // 自己退群
			if(roomMember.getRole() >= 3)
				throw new ServiceException("暂无踢人权限");
			if(room.getUserId().equals(userId)){
				throw new ServiceException("不能移出群主");
			}
			// 处理管理员踢管理员和隐身人监护人的问题
			if(member.getRole() != 1 && member.getRole() != 3){
				// 处理群主和后台管理员踢人问题
				if(2 == roomMember.getRole())
					throw new ServiceException("管理员不能踢出"+(2 == member.getRole() ? "管理员" : 4 == member.getRole() ? "隐身人" : "监护人"));
			}
		}
		User toUser = getUserManager().getUser(userId);
		// IMPORTANT 1-4、删除成员推送-已改
		MessageBean messageBean = new MessageBean();
		messageBean.setFromUserId(user.getUserId() + "");
		messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
		messageBean.setType(KXMPPServiceImpl.DELETE_MEMBER);
		// messageBean.setObjectId(roomId.toString());
		messageBean.setObjectId(room.getJid());
		if(user.getUserId().equals(userId)){
			messageBean.setTo(room.getUserId()+"");
		}
		messageBean.setToUserId(userId + "");
		messageBean.setToUserName(toUser.getNickname());
		messageBean.setContent(room.getName());
		messageBean.setMessageId(StringUtil.randomUUID());
		// 群组减员发送通知
		if(1 == room.getIsAttritionNotice()){
			if(KConstants.Room_Role.INVISIBLE != member.getRole() && KConstants.Room_Role.GUARDIAN != member.getRole()){
			// 发送单聊通知被踢出本人、群聊
			sendChatToOneGroupMsg(userId, room.getJid(), messageBean);
			}else{
				sendGroupOne(userId, messageBean);
			}
		}
		else
			sendGroupOne(userId, messageBean);

		/**
		 * 删除分表下的群成员数据
		 */
		Document query = new Document().append("roomId", roomId).append("userId", userId);
		/**
		 * 删除分表下群成员加入群组jid
		 */
		delJidsByUserId(userId, room.getJid());
		getCollection(roomId).deleteOne(query);

		updateUserSize(roomId, -1);

		/**
		 * 删除 用户加入的群组 jid  缓存
		 */
		SKBeanUtils.getRedisService().deleteUserRoomJidList(userId);
		SKBeanUtils.getRedisService().removeRoomPushMember(room.getJid(), userId);
		/**
		 * 维护群组、群成员 缓存
		 */
		updateRoomInfoByRedis(roomId.toString());
		// 更新群组相关设置操作时间
		updateOfflineOperation(user.getUserId(), roomId,null);
	}

	/**
	 * 发送 907 邀请群成员 进群消息 单聊和群聊
	 */
	public void sendNewMemberMessage(int fromUserId,Room room,Member member){
		MessageBean messageBean=createNewMemberMessage(fromUserId,room,member);

		// 发送单聊通知到被邀请人， 群聊
		sendChatToOneGroupMsg(member.getUserId(), room.getJid(), messageBean);
	}

	/*
	*907 邀请群成员消息  只发送单聊
	* */
	public void sendToChatNewMemberMessage(int fromUserId,Room room,Member member){
		// IMPORTANT 1-7、新增成员
		MessageBean messageBean=createNewMemberMessage(fromUserId,room,member);

		// 发送单聊通知到被邀请人
		messageBean.setMsgType(0);
		if(StringUtil.isEmpty(messageBean.getMessageId()))
			messageBean.setMessageId(StringUtil.randomUUID());
		KXMPPServiceImpl.getInstance().send(messageBean);

	}
	private MessageBean createNewMemberMessage(int fromUserId,Room room,Member member){
		// IMPORTANT 1-7、新增成员
		MessageBean messageBean = new MessageBean();
		messageBean.setType(KXMPPServiceImpl.NEW_MEMBER);
		// messageBean.setObjectId(roomId.toString());
		messageBean.setObjectId(room.getJid());
		messageBean.setFromUserId(fromUserId+ "");
		messageBean.setFromUserName(getUserManager().getNickName(fromUserId));
		messageBean.setToUserId(member.getUserId()+ "");
		messageBean.setToUserName(member.getNickname());
		messageBean.setFileSize(room.getShowRead());
		messageBean.setContent(room.getName());
		messageBean.setFileName(room.getId().toString());

		JSONObject jsonObject=new JSONObject();
		jsonObject.put("showRead", room.getShowRead());
		jsonObject.put("lsLook", room.getIsLook());
		jsonObject.put("isNeedVerify", room.getIsNeedVerify());
		jsonObject.put("showMember", room.getShowMember());
		jsonObject.put("allowSendCard", room.getAllowSendCard());
		jsonObject.put("maxUserSize", room.getMaxUserSize());
		jsonObject.put("isSecretGroup",room.getIsSecretGroup());
		jsonObject.put("chatKeyGroup",member.getChatKeyGroup());

		messageBean.setOther(jsonObject.toJSONString());
		messageBean.setMessageId(StringUtil.randomUUID());
		return  messageBean;

	}

	@Override
	public void updateMember(User user, ObjectId roomId, List<Integer> userIdList,JSONObject userKeys) {
		Room room = get(roomId);
		Member invitationMember = getMember(roomId, user.getUserId());
		if(null != invitationMember && 4 == invitationMember.getRole())
			throw new ServiceException("隐身人不可以邀请用户加群");
		if(room.getMaxUserSize() <room.getUserSize()+userIdList.size())
			throw new ServiceException("群人数快到上限  最多还可以邀请  "+(room.getMaxUserSize()-room.getUserSize())+"人") ;
		List<Member> list=new ArrayList<>();
		for (int userId : userIdList) {
			User _user = getUserManager().getUser(userId);
			if(null==_user)
				continue;
			Member _member = new Member();
			if(-1<findMemberAndRole(roomId, userId)) {
				logger.info(" 用户   {}   已经加入群组   ",userId);
				continue;
			}

			_member.setUserId(userId);
			_member.setRole(3);
			updateMember(user, roomId, _member);
		}

		//getRoomDatastore().save(list);

		updateUserSize(roomId, list.size());

		list.stream().forEach(member ->{
			// IMPORTANT 1-7、新增成员
				MessageBean messageBean = new MessageBean();
				messageBean.setType(KXMPPServiceImpl.NEW_MEMBER);
				// messageBean.setObjectId(roomId.toString());
				messageBean.setObjectId(room.getJid());
				messageBean.setFromUserId(user.getUserId() + "");
				messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
				messageBean.setToUserId(member.getUserId()+ "");
				messageBean.setToUserName(member.getNickname());

				messageBean.setFileSize(room.getShowRead());
				messageBean.setContent(room.getName());
				messageBean.setFileName(room.getId().toString());

				JSONObject jsonObject=new JSONObject();
				jsonObject.put("showRead", room.getShowRead());
				jsonObject.put("lsLook", room.getIsLook());
				jsonObject.put("isNeedVerify", room.getIsNeedVerify());
				jsonObject.put("showMember", room.getShowMember());
				jsonObject.put("allowSendCard", room.getAllowSendCard());
				jsonObject.put("maxUserSize", room.getMaxUserSize());
				messageBean.setOther(jsonObject.toJSONString());
				messageBean.setMessageId(StringUtil.randomUUID());

				// 发送单聊通知到被邀请人， 群聊
				sendChatToOneGroupMsg(member.getUserId(), room.getJid(), messageBean);
				// 维护用户加入的群jids
				saveJidsByUserId(member.getUserId(),room.getJid(), room.getId());
				/**
				 * 删除 用户加入的群组 jid  缓存
				 */
				SKBeanUtils.getRedisService().deleteUserRoomJidList(member.getUserId());
				if(0==SKBeanUtils.getUserManager().getOnlinestateByUserId(member.getUserId())) {
					SKBeanUtils.getRedisService().addRoomPushMember(room.getJid(),member.getUserId());
				}
		});


		/**
		 * 维护群组、群成员缓存
		 */
		updateRoomInfoByRedis(roomId.toString());
		// 更新群组相关设置操作时间
		updateOfflineOperation(user.getUserId(), roomId,StringUtil.getIntegerByList(userIdList, ","));
	}
	
	@Override
	public void updateMember(User user, ObjectId roomId, Member member) {
		Room room = getRoom(roomId,user.getUserId());
		if(null != room && room.getS() == -1)
			throw new ServiceException(KConstants.ResultCode.RoomIsLock);
		Member oldMember = getMember(roomId, member.getUserId());

		User toUser = getUserManager().getUser(member.getUserId());

		if (null!=oldMember) {
			Document document = new Document();
			if (!member.getUserId().equals(user.getUserId())&&0!= member.getRole()){
				document.append("role", member.getRole());
			}
			if (null != member.getSub()){
				document.append("sub", member.getSub());
			}
			if (null != member.getTalkTime()){
				document.append("talkTime", member.getTalkTime());
			}
			if (!StringUtil.isEmpty(member.getNickname())){
				document.append("nickname", member.getNickname());
				document.append("nicknameModifyTime", DateUtil.currentTimeSeconds());
			}
			if (!StringUtil.isEmpty(member.getRemarkName())){
				document.append("remarkName", member.getRemarkName());
			}
			if(member.getWinRate() > -1)
			{
				document.append("winRate", member.getWinRate());
			}
			logger.info("[updateMember]=" + member.getWinRate());
			document.append("modifyTime", DateUtil.currentTimeSeconds());
			document.append("call", room.getCall());
			document.append("videoMeetingNo", room.getVideoMeetingNo());

			/**
			 * 修改分库分表后的群成员信息
			 */
			updateRoomMemberToDB(roomId, member.getUserId(), document);

			if (!StringUtil.isEmpty(member.getNickname()) && !oldMember.getNickname().equals(member.getNickname())) {
				// IMPORTANT 1-1、改昵称推送-已改
				MessageBean messageBean = new MessageBean();
				messageBean.setType(KXMPPServiceImpl.CHANGE_NICK_NAME);
				// messageBean.setObjectId(roomId.toString());
				messageBean.setObjectId(room.getJid());
				messageBean.setFromUserId(user.getUserId() + "");
				messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
				messageBean.setToUserId(toUser.getUserId() + "");
				messageBean.setToUserName(oldMember.getNickname());
				messageBean.setContent(member.getNickname());
				messageBean.setMessageId(StringUtil.randomUUID());
				// 发送群聊
				sendGroupMsg(room.getJid(), messageBean);
			}
			if (null != member.getTalkTime()) {
				// IMPORTANT 1-6、禁言
				MessageBean messageBean = new MessageBean();
				messageBean.setType(KXMPPServiceImpl.GAG);
				// messageBean.setObjectId(roomId.toString());
				messageBean.setObjectId(room.getJid());
				messageBean.setFromUserId(user.getUserId() + "");
				messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
				messageBean.setToUserId(toUser.getUserId() + "");
				messageBean.setToUserName(oldMember.getNickname());
				messageBean.setContent(member.getTalkTime() + "");
				messageBean.setMessageId(StringUtil.randomUUID());
				// 发送单聊通知被禁言的人,群聊
				sendChatToOneGroupMsg(toUser.getUserId(), room.getJid(), messageBean);
			}
		} else {
			Member invitationMember = getMember(roomId, user.getUserId());
			if(null != invitationMember && 4 == invitationMember.getRole())
				throw new ServiceException("隐身人不可以邀请用户加群");
			if(room.getMaxUserSize() < room.getUserSize()+1)
				throw new ServiceException("群人数已达到上限，不能继续加入");
			User _user = getUserManager().getUser(member.getUserId());
			Member _member = new Member();
			_member.setActive(DateUtil.currentTimeSeconds());
			_member.setCreateTime(_member.getActive());
			_member.setModifyTime(0L);
			_member.setNickname(_user.getNickname());
			_member.setRole(member.getRole());
			_member.setRoomId(roomId);
			_member.setSub(1);
			_member.setTalkTime(0L);
			_member.setUserId(_user.getUserId());
			_member.setRole(3);
			/**
			 * 群成员分表保存
			 */
			DBObject dbObj = objectToDBObject(_member);
			getDBObjectCollection(roomId).insertOne(dbObj);
//
			updateUserSize(roomId, 1);

			// IMPORTANT 1-7、新增成员
			MessageBean messageBean = new MessageBean();
			messageBean.setType(KXMPPServiceImpl.NEW_MEMBER);
			messageBean.setObjectId(room.getJid());
			messageBean.setFromUserId(user.getUserId() + "");
			messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
			messageBean.setToUserId(toUser.getUserId() + "");
			messageBean.setToUserName(toUser.getNickname());
			
			
			messageBean.setFileSize(room.getShowRead());
			messageBean.setContent(room.getName());
			messageBean.setFileName(room.getId().toString());
			
			JSONObject jsonObject=new JSONObject();
			jsonObject.put("showRead", room.getShowRead());
			jsonObject.put("lsLook", room.getIsLook());
			jsonObject.put("isNeedVerify", room.getIsNeedVerify());
			jsonObject.put("showMember", room.getShowMember());
			jsonObject.put("allowSendCard", room.getAllowSendCard());
			jsonObject.put("maxUserSize", room.getMaxUserSize());
			messageBean.setOther(jsonObject.toJSONString());
			messageBean.setMessageId(StringUtil.randomUUID());
			
			// 发送单聊通知到被邀请人， 群聊
			sendChatToOneGroupMsg(toUser.getUserId(), room.getJid(), messageBean);
			// 维护用户加入的群jids
			saveJidsByUserId(toUser.getUserId(),room.getJid(),roomId);
			/**
			 * 删除 用户加入的群组 jid  缓存
			 */
			SKBeanUtils.getRedisService().deleteUserRoomJidList(member.getUserId());
			if(0==SKBeanUtils.getUserManager().getOnlinestateByUserId(member.getUserId())) {
				SKBeanUtils.getRedisService().addRoomPushMember(room.getJid(), member.getUserId());
			}
		}
		
		/**
		 * 维护群组、群成员缓存
		 */
		updateRoomInfoByRedis(roomId.toString());
		// 更新群组相关设置操作时间
		updateOfflineOperation(user.getUserId(), roomId,null);

	}
	public MemberRate getMemberRateInfo(MemberRate member,int userId)
	{
		Member invitationMember = getMember(member.getRoomId(), userId);
		if(invitationMember.getRole() != 2 && invitationMember.getRole() != 1) return null;
		MemberRate oldMember = getMemberRate(member.getRoomId(), member.getUserId());
		return oldMember;
	}
	public MemberRate getMemberRateInfo(ObjectId roomId,int userId)
	{

		MemberRate oldMember = getMemberRate(roomId, userId);
		return oldMember;
	}
	public void updateMemberRate(MemberRate member,int userId )
    {
        Member invitationMember = getMember(member.getRoomId(), userId);
        if(invitationMember.getRole() != 2 && invitationMember.getRole() != 1) return;


        MemberRate oldMember = getMemberRate(member.getRoomId(), member.getUserId());

        Document document = new Document();
        MongoCollection<Document> collection   = getImRoomDatabase().getCollection("shiku_room_member_winrate");
        if (null != member.getWinRate1()){
            document.append("winRate1", member.getWinRate1());
        }
        if (null != member.getWinRate2()){
            document.append("winRate2", member.getWinRate2());
        }
        if (null != member.getWinRate3()){
            document.append("winRate3", member.getWinRate3());
        }
        if (null != member.getWinRate4()){
            document.append("winRate4", member.getWinRate4());
        }
        if (null != member.getWinRate5()){
            document.append("winRate5", member.getWinRate5());
        }
        if (null != member.getWinRate6()){
            document.append("winRate6", member.getWinRate6());
        }
        if (null != member.getWinRate7()){
            document.append("winRate7", member.getWinRate7());
        }
        if (null != member.getWinRate8()){
            document.append("winRate8", member.getWinRate8());
        }
        if (null != member.getWinRate9()){
            document.append("winRate9", member.getWinRate9());
        }
        if (null != member.getWinRate10()){
            document.append("winRate10", member.getWinRate10());
        }
        if (null != member.getWinRate11()){
            document.append("winRate11", member.getWinRate11());
        }
        if (null != member.getWinRate12()){
            document.append("winRate12", member.getWinRate12());
        }
        if (null != member.getWinRate13()){
            document.append("winRate13", member.getWinRate13());
        }
        if (null != member.getWinRate14()){
            document.append("winRate14", member.getWinRate14());
        }
        if (null != member.getWinRate15()){
            document.append("winRate15", member.getWinRate15());
        }
        if (null != member.getWinRate16()){
            document.append("winRate16", member.getWinRate16());
        }
        if (null != member.getWinRate17()){
            document.append("winRate17", member.getWinRate17());
        }
        if (null != member.getWinRate18()){
            document.append("winRate18", member.getWinRate18());
        }
		if (null != member.getWinRate19()){
			document.append("winRate19", member.getWinRate19());
		}
		if (null != member.getWinRate20()){
			document.append("winRate20", member.getWinRate20());
		}
		if (null != member.getWinRate21()){
			document.append("winRate21", member.getWinRate21());
		}
		if (null != member.getWinRate22()){
			document.append("winRate22", member.getWinRate22());
		}
		if (null != member.getWinRate23()){
			document.append("winRate23", member.getWinRate23());
		}
		if (null != member.getWinRate24()){
			document.append("winRate24", member.getWinRate24());
		}
		if (null != member.getWinRate25()){
			document.append("winRate25", member.getWinRate25());
		}
		if (null != member.getWinRate26()){
			document.append("winRate26", member.getWinRate26());
		}
		if (null != member.getWinRate27()){
			document.append("winRate27", member.getWinRate27());
		}
		if (null != member.getWinRate28()){
			document.append("winRate28", member.getWinRate28());
		}
		if (null != member.getWinRate29()){
			document.append("winRate29", member.getWinRate29());
		}
		if (null != member.getWinRate30()){
			document.append("winRate30", member.getWinRate30());
		}
		if (null != member.getWinRate31()){
			document.append("winRate31", member.getWinRate31());
		}
		if (null != member.getWinRate32()){
			document.append("winRate32", member.getWinRate32());
		}
		if (null != member.getWinRate33()){
			document.append("winRate33", member.getWinRate33());
		}
		if (null != member.getWinRate34()){
			document.append("winRate34", member.getWinRate34());
		}
		if (null != member.getWinRate35()){
			document.append("winRate35", member.getWinRate35());
		}
		if (null != member.getWinRate36()){
			document.append("winRate36", member.getWinRate36());
		}
		if (null != member.getWinRate37()){
			document.append("winRate37", member.getWinRate37());
		}
		if (null != member.getWinRate38()){
			document.append("winRate38", member.getWinRate38());
		}
        if(oldMember != null)
        {
            Document query = new Document("roomId", member.getRoomId()).append("userId", member.getUserId());
            collection.updateOne(query, new Document("$set", document));
        }
        else{

            document.append("roomId", member.getRoomId());
            document.append("userId", member.getUserId());
            collection.insertOne(document);
        }
    }

    public  void updateAllMemberRate(String RoomId, int userId)
    {
        Member invitationMember = getMember(new ObjectId(RoomId), userId);
        if(invitationMember.getRole() != 2 && invitationMember.getRole() != 1) return;

        Document document = new Document();
        document.append("winRate1", -1.0);
        document.append("winRate2", -1.0);
        document.append("winRate3", -1.0);
        document.append("winRate4", -1.0);
        document.append("winRate5", -1.0);
        document.append("winRate6", -1.0);
        document.append("winRate7", -1.0);
        document.append("winRate8", -1.0);
        document.append("winRate9", -1.0);
        document.append("winRate10", -1.0);
        document.append("winRate11", -1.0);
        document.append("winRate12", -1.0);
        document.append("winRate13", -1.0);
        document.append("winRate14", -1.0);
        document.append("winRate15", -1.0);
        document.append("winRate16", -1.0);
        document.append("winRate17", -1.0);
        document.append("winRate18", -1.0);
        document.append("winRate19", -1.0);
        document.append("winRate20", -1.0);
        document.append("winRate21", -1.0);
        document.append("winRate22", -1.0);
        document.append("winRate23", -1.0);
        document.append("winRate24", -1.0);
        document.append("winRate25", -1.0);
        document.append("winRate26", -1.0);
        document.append("winRate27", -1.0);
        document.append("winRate28", -1.0);
        document.append("winRate29", -1.0);
        document.append("winRate30", -1.0);
        document.append("winRate31", -1.0);
        document.append("winRate32", -1.0);
        document.append("winRate33", -1.0);
        document.append("winRate34", -1.0);
        document.append("winRate35", -1.0);
        document.append("winRate36", -1.0);
        document.append("winRate37", -1.0);
        document.append("winRate38", -1.0);
        MongoCollection<Document> collection   = getImRoomDatabase().getCollection("shiku_room_member_winrate");
        Document query = new Document("roomId", new ObjectId(RoomId));
        collection.updateOne(query, new Document("$set", document));
    }
	@Override
   public Member getMember(ObjectId roomId,int userId) {
		MongoCollection<Document> collection = getCollection(roomId);
		//MongoCollection<Document> collection = getCollection(userId);
		
		Document query = new Document("roomId", roomId).append("userId", userId);
		Document document = collection.find(query).first();
		Member member=null;
		if(null==document)
			return null;
		member =DocumentToJavaBean.setFieldValue( new Member(), document);
		//如果没有修改过昵称，那么读取用户基本信息表数据
		if(!document.containsKey("nicknameModifyTime"))
		{
			member.setNickname(SKBeanUtils.getUserManager().getNickName(userId));
		}
	
		return member;

	}
	public Member getMemberByAccount(ObjectId roomId,String account)
	{
		User _user = getUserManager().getUserByAccount(account);
		if(_user == null) return null;
		return getMember(roomId,_user.getUserId());
	}
	public  MemberRate getMemberRate(ObjectId roomId,int userId)
    {
        MongoCollection<Document> collection   = getImRoomDatabase().getCollection("shiku_room_member_winrate");
        Document query = new Document("roomId", roomId).append("userId", userId);
        Document document = collection.find(query).first();
        MemberRate member=null;
        if(null==document)
            return null;
        member =DocumentToJavaBean.setFieldValue( new MemberRate(), document);
        return member;
    }
	public void updateRoomMemberToDB(ObjectId roomId, int userId,Document values) {
		MongoCollection collection = getCollection(roomId);
		Document query = new Document("roomId", roomId).append("userId", userId);
		collection.updateOne(query, new Document("$set", values));
	}
	public int findMemberAndRole(ObjectId roomId, int userId) {
		MongoCollection<Document> collection = getCollection(roomId);
		Document projection=new Document("role", 1);
		Document query=new Document("roomId", roomId);
		query.append("userId", userId);
		Document first = collection.find(query).projection(projection).first();
		int role=-1;
		if(null!=first){
			role=first.getInteger("role");
		}
		return role;
	}

	
	
	@Override
	public void Memberset(Integer offlineNoPushMsg, ObjectId roomId,int userId,int type) {

		String jid = queryRoomJid(roomId);
		 long currentTime = DateUtil.currentTimeSeconds();

		Document values = new Document("modifyTime", currentTime);
		if(0==type) {
			if(1==offlineNoPushMsg) {
				SKBeanUtils.getRedisService().addToRoomNOPushJids(userId, jid);
			}else {
				SKBeanUtils.getRedisService().removeToRoomNOPushJids(userId, jid);
			}
			values.append("offlineNoPushMsg",offlineNoPushMsg);
		}else if(1 == type){
			values.append("openTopChatTime",(offlineNoPushMsg == 0 ? 0 : currentTime));
		}
	   
		logger.info("[ww]:Memberset offlineNoPushMsg="+offlineNoPushMsg+",roomId="+roomId+",userId="+userId);
		
		/**
		 * 修改分库分表下对应群成员数据
		 */
		getCollection(roomId).updateOne(new Document("roomId",roomId).append("userId", userId), new Document(MongoOperator.SET,values));
		getCollection(userId).updateOne(new Document("roomId",roomId).append("userId", userId), new Document(MongoOperator.SET,values));
		// 维护群组、群成员相关属性
		updateRoomInfoByRedis(roomId.toString());
		// 多点登录维护数据
		if(getUserManager().isOpenMultipleDevices(userId)){
			String nickName = getUserManager().getNickName(userId);
			multipointLoginUpdateUserInfo(userId, nickName, userId, nickName, roomId);
		}
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<Member> getMemberList(ObjectId roomId,String keyword) {
		List<Member>list=null;
		if(!StringUtil.isEmpty(keyword)){
			List<Document> containsIgnoreCase = containsIgnoreCase(keyword, "nickname", roomId);
			List<Member> members = new ArrayList<Member>();
				containsIgnoreCase.forEach(document ->{
					try {
						Member member= DocumentToJavaBean.setFieldValue(new Member(), document);
						if(!document.containsKey("nicknameModifyTime") && null!=member) 
						{
							member.setNickname(SKBeanUtils.getUserManager().getNickName(member.getUserId()));
							logger.info("[ww]:getMember.getNickName="+member.getNickname());
						}
						if(null!=member)
							members.add(member);
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}

				});
				return members;
		}else{
			List<Member> memberList = getRedisServiceImpl().getMemberList(roomId.toString());
			if(null != memberList && memberList.size() > 0){
				return memberList;
			}else{
				List<Member> memberDBList = new ArrayList<Member>();
				Document query = new Document().append("roomId", roomId);;
				MongoCursor<Document> iterator = getCollection(roomId).find(query).sort(new Document("createTime",-1)).iterator();

				try {
					Member member=null;
					while(iterator.hasNext()){
						Document document = iterator.next();
						member = (Member)DocumentToJavaBean.setFieldValue(new Member(), document);
						if(null!=member)
							memberDBList.add(member);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}finally {
					iterator.close();
				}
				getRedisServiceImpl().saveMemberList(roomId.toString(), memberDBList);

				return memberDBList;
			}
		}
	}

	/** @Description:获取群组中的群主和管理员
	* @param roomId
	* @return
	**/
	public List<Member> getAdministrationMemberList(ObjectId roomId) {
		List<Member> members = new ArrayList<>();
		try {
			MongoCollection<Document> collection = getCollection(roomId);
			Document query=new Document("roomId", roomId);
			query.append("role", new Document("$lt", 3));
			MongoCursor<Document> iterator = collection.find(query).iterator();
			Document doc=null;
			Member member=null;

			try {
				while(iterator.hasNext()){
					doc=iterator.next();
					member =  DocumentToJavaBean.setFieldValue(new Member(), doc);
					if(null!=member) {
						User _user = SKBeanUtils.getUserManager().getUser(member.getUserId());
						if (_user != null) member.setAccounts(_user.getAccount());
						members.add(member);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally {
				iterator.close();
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		return members;
	}

	/** @Description: 普通群成员userId列表，除了管理员和群主
	* @param roomId
	* @return
	**/ 
	@SuppressWarnings("unchecked")
	public List<Integer> getCommonMemberIdList(ObjectId roomId) {
		// 分库分表
		List<Integer> userIds = new ArrayList<Integer>();
		Document query=new Document("roomId",roomId);
		query.append("role", 3);
		MongoCursor<Integer> iterator = getCollection(roomId).distinct("userId",query, Integer.class).iterator();

		try {
			while(iterator.hasNext()){
				Integer next = iterator.next();
				userIds.add(next);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}
		return userIds;
	}
	/** @Description: 群成员userId列表
	* @param roomId
	* @return
	**/ 
	public List<Integer> getMemberIdList(ObjectId roomId) {
		// 分库分表
		List<Integer> userIds = new ArrayList<Integer>();
		Document query=new Document("roomId",roomId);
		MongoCursor<Integer> iterator = getCollection(roomId).distinct("userId",query, Integer.class).iterator();

		try {
			while(iterator.hasNext()){
				Integer next = iterator.next();
				userIds.add(next);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}
		return userIds;
	}
	
	@SuppressWarnings("unchecked")
	public List<ObjectId> getRoomIdList(Integer userId) {
		// 分库分表
		List<ObjectId> roomIds = new ArrayList<ObjectId>();
		MongoCursor<ObjectId> iterator = getCollection(userId).distinct("roomId",new Document("userId", userId), ObjectId.class).iterator();

		try {
			while(iterator.hasNext()){
				ObjectId next = iterator.next();
				roomIds.add(next);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}


		return roomIds;
	}
	
	/**
	 * 查询成员是否开启 免打扰
	 * @param roomId
	 * @param userId
	 * @return
	 */
	public boolean getMemberIsNoPushMsg(ObjectId roomId, int userId) {

		Document query = new Document().append("roomId", roomId).append("userId", userId).append("offlineNoPushMsg", 1);
		Document document = getCollection(roomId).find(query).first();
		if(null==document)
			return false;
		else
		return true;
	}
	
	public String getMemberNickname(ObjectId roomId,Integer userId){
		String nickname = null;
		// 后台修改群组配置以10005系统号发送
		if(10005 == userId)
			return String.valueOf(10005);
		if(0 != userId){
			Member member = getMember(roomId, userId);
			if(null == member)
				return "";
			else
				nickname =member.getNickname();
		}
		return nickname;
	}
	
	/*公告列表*/
	public List<Notice> getNoticeList(ObjectId roomId){
		List<Notice> notices;
		Room roomCache = getRedisServiceImpl().queryRoom(roomId);
		if(null != roomCache)
			notices = roomCache.getNotices();
		else{
			List<Notice> noticesDB = getRoomDatastore().createQuery(Room.Notice.class).field("roomId").equal(roomId).asList();
			notices = noticesDB;
		}
		return notices;
	}
	
	/*公告列表*/
	public PageVO getNoticeList(ObjectId roomId,Integer pageIndex,Integer pageSize){
		
		Query<Notice> query = getRoomDatastore().createQuery(Room.Notice.class).field("roomId").equal(roomId).order("-time");
		long total = query.count();
		List<Notice> pageData = query.offset(pageIndex * pageSize).limit(pageSize).asList();
		return new PageVO(pageData, total, pageIndex, pageSize);
	}
	
	public Notice updateNotice(ObjectId roomId,ObjectId noticeId,String noticeContent,Integer userId){
		Query<Notice> query = getRoomDatastore().createQuery(Room.Notice.class).field("roomId").equal(roomId).field("_id").equal(noticeId);
		UpdateOperations<Notice> ops = SKBeanUtils.getDatastore().createUpdateOperations(Notice.class);
		ops.set("text", noticeContent);
		ops.set("modifyTime", DateUtil.currentTimeSeconds());
		getDatastore().update(query, ops);
		Notice notice = query.get();
		// 维护最新一条公告
		Room room = getRoom(roomId,userId);
		if(room.getNotice().getId().equals(noticeId)){
			getRedisServiceImpl().deleteRoom(String.valueOf(roomId));
			updateAttribute(roomId, "notice", notice);
		}
		getRedisServiceImpl().deleteNoticeList(roomId);
		ThreadUtil.executeInThread(obj -> {
			MessageBean messageBean = new MessageBean();
			messageBean.setFromUserId(userId + "");
			messageBean.setFromUserName(getMemberNickname(room.getId(), userId));
			messageBean.setType(KXMPPServiceImpl.ModifyNotice);
			messageBean.setObjectId(room.getJid());
			messageBean.setContent(noticeContent);
			messageBean.setMessageId(StringUtil.randomUUID());
			// 发送群聊
			sendGroupMsg(room.getJid(), messageBean);
		});
		return notice;
	}

	public void deleteNotice(ObjectId roomId, ObjectId noticeId) {
		Query<Notice> query = getRoomDatastore().createQuery(Notice.class);
		query.filter("_id", noticeId);
		query.filter("roomId", roomId);
		getRoomDatastore().delete(query);
		// 维护room最新公告
		Room room = getRoom(roomId,ReqUtil.getUserId());
		if (null != room.getNotice() && noticeId.equals(room.getNotice().getId())) {
			updateAttribute(roomId, "notice", new Notice());
		}
		/**
		 * 维护群组信息 、公告缓存
		 */
		getRedisServiceImpl().deleteNoticeList(roomId);
		getRedisServiceImpl().deleteRoom(roomId.toString());
	}
	
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public PageResult<Document> getMemberListByPage(ObjectId roomId,int pageIndex,int pageSize) {
		List<Document> members = new ArrayList<Document>();
		Document query = new Document("roomId", roomId);
		MongoCollection collection = getCollection(roomId);
		long count = collection.count(query);
		MongoCursor<Document> iterator =collection.find(query).sort(new Document("createTime", -1)).skip((pageIndex-1)*pageSize).limit(pageSize).iterator();

		try {
			while (iterator.hasNext()) {
				Document document = iterator.next();

				members.add(document);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			iterator.close();
		}
		return new PageResult<Document>(members,count);
	}
	

	@Override
	public void join(int userId, ObjectId roomId, int type) {
		Room room = getRoom(roomId);
		if(room != null){
			if(room.getUserSize()+1>room.getMaxUserSize()){
				throw new ServiceException(KConstants.ResultCode.RoomMemberAchieveMax);
			}
		}else{
			throw new ServiceException(KConstants.ResultCode.NotRoom);
		}
		Member member = new Member();
		member.setUserId(userId);
		member.setRole(1 == type ? 1 : 3);
		updateMember(getUserManager().getUser(userId), roomId, member);
	}

	// 扫码加群
	public void sweepCode(ObjectId roomId,User user,Member member){
		Room room = getRoom(roomId,user.getUserId());
		if(null != room && room.getS() == -1)
			throw new ServiceException(KConstants.ResultCode.RoomIsLock);
		User toUser = getUserManager().getUser(member.getUserId());
		if(room.getMaxUserSize() < room.getUserSize()+1)
			throw new ServiceException(KConstants.ResultCode.RoomMemberAchieveMax);
		User memberUser = getUserManager().getUser(member.getUserId());
		Member _member = new Member(roomId,memberUser.getUserId(),memberUser.getNickname());
		getRoomDatastore().save(_member);
		updateUserSize(roomId, 1);

		// 发送单聊通知到被邀请人， 群聊
		sendNewMemberMessage(user.getUserId(),room,_member);
		// 维护用户加入的群jids
		saveJidsByUserId(toUser.getUserId(),room.getJid(),roomId);
		/**
		 * 删除 用户加入的群组 jid  缓存
		 */
		SKBeanUtils.getRedisService().deleteUserRoomJidList(member.getUserId());
		if(0==SKBeanUtils.getUserManager().getOnlinestateByUserId(member.getUserId())) {
			SKBeanUtils.getRedisService().addRoomPushMember(room.getJid(), member.getUserId());
		}
		/**
		 * 维护群组、群成员缓存
		 */
		updateRoomInfoByRedis(roomId.toString());
		// 更新群组相关设置操作时间
		updateOfflineOperation(user.getUserId(), roomId,null);
	}
	
	public void joinRoom(Integer userId,String name,ObjectId roomId,long currentTime,Integer adminUserId) {
		Room room = getRoom(roomId);
		if(room == null){
			throw new ServiceException("房间不存在");
		}
		List<Member> memberList=Collections.synchronizedList(new ArrayList<Member>());
		List<MessageBean> messageList=Collections.synchronizedList(new ArrayList<MessageBean>());
		JSONObject jsonObject=new JSONObject();
		jsonObject.put("showRead", room.getShowRead());
		jsonObject.put("lsLook", room.getIsLook());
		jsonObject.put("isNeedVerify", room.getIsNeedVerify());
		jsonObject.put("showMember", room.getShowMember());
		jsonObject.put("allowSendCard", room.getAllowSendCard());
		jsonObject.put("maxUserSize", room.getMaxUserSize());
		Member member = new Member(roomId,userId,name);
		memberList.add(member);
		/**
		 * 分库分表分表保存群成员
		 */
		DBObject dbObject = objectToDBObject(member);
		getDBObjectCollection(roomId).insertOne(dbObject);
//
		/**
		 * 分库分表保存用户加入的群jid
		 */
		saveJidsByUserId(userId, queryRoomJid(roomId), roomId);

		MessageBean messageBean = new MessageBean();
		messageBean.setType(KXMPPServiceImpl.NEW_MEMBER);
		messageBean.setObjectId(room.getJid());
		messageBean.setFromUserId(userId + "");
		messageBean.setFromUserName(member.getNickname());
		messageBean.setToUserId(userId+"");
		messageBean.setToUserName(member.getNickname());
		messageBean.setFileSize(room.getShowRead());
		messageBean.setContent(room.getName());
		messageBean.setFileName(room.getId().toString());
		messageBean.setOther(jsonObject.toJSONString());
		messageBean.setMessageId(StringUtil.randomUUID());

		messageList.add(messageBean);
		updateUserSize(room.getId(), 1);
		/**
		 * 维护群组、群成员缓存
		 */
		updateRoomInfoByRedis(roomId.toString());
		
		KXMPPServiceImpl.getInstance().sendManyMsgToGroupByJid(room.getJid(), messageList);
	}

	public void updateUserSize(ObjectId roomId, int userSize) {
		DBObject q = new BasicDBObject("_id", roomId);
		DBObject o = new BasicDBObject("$inc", new BasicDBObject("userSize", userSize));
		getRoomDatastore().getCollection(getEntityClass()).update(q, o);
	}


	public void leave(int userId, ObjectId roomId) {

	}

	public Room exisname(Object roomname,ObjectId roomId) {
		Query<Room> query = getRoomDatastore().createQuery(getEntityClass());
		query.field("name").equal(roomname);
		if(null!=roomId)
			query.field("_id").notEqual(roomId);
		Room room = query.get();
		return room;
	}

	
	/**
	* @Description: TODO(删除 群共享的文件 和 群聊天消息的文件)
	* @param @param roomId
	* @param @param roomJid    参数
	 */
	public void destroyRoomMsgFileAndShare(ObjectId roomId,String roomJid){
		//删除共享文件 
		Query<Share> shareQuery = getRoomDatastore().createQuery(Room.Share.class).field("roomId").equal(roomId);

		List<String> shareList = getRoomDatastore().getCollection(Share.class).distinct("url",shareQuery.getQueryObject());
		for (String url : shareList) {
			try {
				ConstantUtil.deleteFile(url);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		getRoomDatastore().delete(shareQuery);
		
		BasicDBObject msgFileQuery=new BasicDBObject("contentType",new BasicDBObject(MongoOperator.IN, MsgType.FileTypeArr));
		List<String> fileList = getRoomDatastore().getDB().getCollection(DBConstants.RoomMsg_Collection_Prefix+roomJid).distinct("content", msgFileQuery);
		for (String url : fileList) {
			try {
				ConstantUtil.deleteFile(url);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		getRoomDatastore().getDB().getCollection(DBConstants.RoomMsg_Collection_Prefix+roomJid).drop();
	}
	
	/**
	*@Description: TODO(解散群组后  删除 tigase 的数据)
	* @param @param roomJid    参数
	* tigase 8.0 后废弃 该 方法
	 */
	@Deprecated()
	public void destroyRoomToIM(String roomJid){

	}
	/**
	* @Description: TODO(群主 通过xmpp 解散群组)
	* @param @param username 群主的userid
	* @param @param password  群主的密码
	* @param @param roomJid     房间jid
	 */
	public void destroyRoomToIM(String username,String password,String roomJid){
		KXMPPServiceImpl.getInstance().destroyMucRoom(username, password, roomJid);
	}
	
	/** @Description:（解散群组后删除群组的离线消息） 
	* @param roomJid
	**/ 
	public void deleMucHistory(String roomJid){
		DBCollection collection =getDatastore().getDB().getCollection("muc_history");
		Pattern regex = Pattern.compile("^" + (roomJid != null ? roomJid : "") + "[^/]*");
		BasicDBObject query = new BasicDBObject("room_jid", regex);
		collection.remove(query);
	}
	//设置/取消管理员
	@Override
	public void setAdmin(ObjectId roomId, int touserId,int type,int userId) {

		getCollection(roomId).updateOne(new Document("roomId",roomId).append("userId", touserId), new Document(MongoOperator.SET, new Document("role",type)));
		// 更新群组、群成员相关缓存
		updateRoomInfoByRedis(roomId.toString());
		String jid = queryRoomJid(roomId);
		//xmpp推送
		MessageBean messageBean=new MessageBean();
		messageBean.setType(KXMPPServiceImpl.SETADMIN);
		if(type==2){//1为设置管理员
			messageBean.setContent(1);
		}else{
			messageBean.setContent(0);
		}
		messageBean.setFromUserId(String.valueOf(userId));
		messageBean.setFromUserName(getMemberNickname(roomId, userId));
		messageBean.setToUserName(getMemberNickname(roomId, touserId));
		messageBean.setToUserId(String.valueOf(touserId));
		messageBean.setObjectId(jid);
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送单聊通知被设置的人、群聊
		sendChatToOneGroupMsg(touserId, jid, messageBean);
	}
	
	/** 设置取消隐身人、监控人
	 * @param roomId
	 * @param touserId
	 * @param type
	 * @param userId
	 */
	@SuppressWarnings("rawtypes")
	public void setInvisibleGuardian(ObjectId roomId, int touserId,int type,int userId) {


		MongoCollection collection = getCollection(roomId);
		// 1=创建者、2=管理员、3=普通成员、4=隐身人、5=监控人
		if(type == -1 || type == 0)
			collection.updateOne(new Document("roomId",roomId).append("userId", touserId), new Document(MongoOperator.SET,new Document("role",3)));
		else if(type == 4 || type == 5){
			collection.updateOne(new Document("roomId",roomId).append("userId", touserId), new Document(MongoOperator.SET,new Document("role",type)));
		}

		/**
		 * 维护群组、群成员相关缓存
		 */
		updateRoomInfoByRedis(roomId.toString());
		Room room=getRoom(roomId);
		User user = getUserManager().getUser(userId);
		//xmpp推送
		MessageBean messageBean=new MessageBean();
		messageBean.setType(KXMPPServiceImpl.SetRoomSettingInvisibleGuardian);
		if(type==4){
			messageBean.setContent(1);
		}else if(type==5){
			messageBean.setContent(2);
		}else if(type == -1){
			messageBean.setContent(-1);
		}else if(type == 0){
			messageBean.setContent(0);
		}
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
		messageBean.setToUserName(getMemberNickname(roomId, touserId));
		messageBean.setToUserId(String.valueOf(touserId));
		messageBean.setObjectId(room.getJid());
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送单聊通知被设置的人、群聊
//		sendChatToOneGroupMsg(q.get().getUserId(), room.getJid(), messageBean);
		sendGroupOne(touserId, messageBean);
	}

	public void updateRoomMemberNickName(int userId,String nickName) {
		MongoDatabase database = SKBeanUtils.getLocalSpringBeanManager().getMongoClient().getDatabase(getCollectionName());
		MongoIterable<String> listCollectionNames = database.listCollectionNames();
		Document query=new Document();
		query.append("userId",userId);
		Document update=new Document(MongoOperator.SET,new Document("nickname", nickName));
		MongoCollection<Document> collection=null;
		for (String string : listCollectionNames) {
			collection = database.getCollection(string);
			collection.updateMany(query, update);
		}

	}
	
	//添加文件（群共享）
	@Override
	public Share Addshare(ObjectId roomId,long size, int type,int userId, String url,String name) {
		User user = getUserManager().getUser(userId);
		Share share=new Share();
		share.setRoomId(roomId);
		share.setTime(DateUtil.currentTimeSeconds());
		share.setNickname(user.getNickname());
		share.setUserId(userId);
		share.setSize(size);
		share.setUrl(url);
		share.setType(type);
		share.setName(name);
		getRoomDatastore().save(share);
		/**
		 * 维护群文件缓存
		 */
		getRedisServiceImpl().deleteShareList(roomId);
		Room room=getRoom(roomId,userId);
		//上传文件xmpp推送
		MessageBean messageBean=new MessageBean();
		messageBean.setType(KXMPPServiceImpl.FILEUPLOAD);
		messageBean.setContent(share.getShareId().toString());
		messageBean.setFileName(share.getName());
		messageBean.setObjectId(room.getJid());
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送群聊通知
		sendGroupMsg(room.getJid(), messageBean);
		return share;
	}
	
	//查询所有
	@Override
	public List<Share> findShare(ObjectId roomId, long time, int userId, int pageIndex, int pageSize) {
		Query<Room.Share> q = getRoomDatastore().createQuery(Room.Share.class).field("roomId").equal(roomId);
		if (userId != 0) {
			q.filter("userId", userId);
		}

		List<Share> list = new ArrayList<Share>();
		list = q.offset(pageSize * pageIndex).limit(pageSize).asList();

		return list;
	}
	
	//删除
	@Override
	public void deleteShare(ObjectId roomId, ObjectId shareId,int userId) {
		Query<Room.Share> q=getRoomDatastore().createQuery(Room.Share.class).field("roomId").equal(roomId).field("shareId").equal(shareId);
		
		User user = getUserManager().getUser(userId);
		Room room=getRoom(roomId,userId);
		Share share=q.get();
		//删除XMpp推送
		MessageBean messageBean=new MessageBean();
		messageBean.setType(KXMPPServiceImpl.DELETEFILE);
		messageBean.setContent(share.getShareId().toString());
		messageBean.setFileName(share.getName());
		messageBean.setObjectId(room.getJid());
		messageBean.setFromUserId(user.getUserId().toString());
		messageBean.setFromUserName(getMemberNickname(roomId, user.getUserId()));
		messageBean.setMessageId(StringUtil.randomUUID());
		// 发送群聊通知
		sendGroupMsg(room.getJid(), messageBean);
		getRoomDatastore().delete(q);
		/**
		 * 维护群文件缓存
		 */
		getRedisServiceImpl().deleteShareList(roomId);
	}
	//获取单个文件
	@Override
	public Share getShare(ObjectId roomId, ObjectId shareId) {
		Share share=getRoomDatastore().createQuery(Room.Share.class).field("roomId").equal(roomId).field("shareId").equal(shareId).get();
		return share;
	}

	@Override
	public String getCall(ObjectId roomId) {
		Room room = getRoomDatastore().createQuery(getEntityClass()).field("_id").equal(roomId).get();
		return room.getCall();
	}

	@Override
	public String getVideoMeetingNo(ObjectId roomId) {
		Room room=getRoomDatastore().createQuery(getEntityClass()).field("_id").equal(roomId).get();
		return room.getVideoMeetingNo();
	}
	
	/**
	 * 发送消息 到群组中
	 * @param jidArr
	 * @param userId
	 * @param msgType
	 * @param content
	 */
	public void sendMsgToRooms(String[] jidArr, int userId,int msgType,String content) {
		User user = SKBeanUtils.getUserManager().getUser(userId);
		MessageBean messageBean=new MessageBean();
		messageBean.setFromUserId(userId+"");
		messageBean.setFromUserName(user.getNickname());
		messageBean.setType(msgType);
		messageBean.setTimeSend(System.currentTimeMillis());
		messageBean.setContent(content);
		messageBean.setMessageId(StringUtil.randomUUID());
		SKBeanUtils.getXmppService().sendMsgToMucRoom(messageBean, jidArr);
	}
	
	/**
	 * 获取房间总数量
	 */
	@Override
    public Long countRoomNum(){
    	long roomNum = getRoomDatastore().createQuery(getEntityClass()).count();
    	return roomNum;
    }
	
	
	/**
	 * 添加群组统计  时间单位每日，最好可选择：每日、每月、每分钟、每小时
	 * @param startDate
	 * @param endDate
	 * @param counType  统计类型   1: 每个月的数据      2:每天的数据       3.每小时数据   4.每分钟的数据 (小时)   
	 */
	public List<Object> addRoomsCount(String startDate, String endDate, short counType){
		
		List<Object> countData = new ArrayList<>();
		
		long startTime = 0; //开始时间（秒）
		
		long endTime = 0; //结束时间（秒）,默认为当前时间
		
		/**
		 * 如时间单位为月和天，默认开始时间为当前时间的一年前 ; 时间单位为小时，默认开始时间为当前时间的一个月前;
		 * 时间单位为分钟，则默认开始时间为当前这一天的0点
		 */
		long defStartTime = counType==4? DateUtil.getTodayMorning().getTime()/1000 
				: counType==3 ? DateUtil.getLastMonth().getTime()/1000 : DateUtil.getLastYear().getTime()/1000;
		
		startTime = StringUtil.isEmpty(startDate) ? defStartTime :DateUtil.toDate(startDate).getTime()/1000;
		endTime = StringUtil.isEmpty(endDate) ? DateUtil.currentTimeSeconds() : DateUtil.toDate(endDate).getTime()/1000;
				
		BasicDBObject queryTime = new BasicDBObject("$ne",null);
		
		if(startTime!=0 && endTime!=0){
			queryTime.append("$gt", startTime);
			queryTime.append("$lt", endTime);
		}
		
		BasicDBObject query = new BasicDBObject("createTime",queryTime);
		
		//获得用户集合对象
		DBCollection collection = SKBeanUtils.getImRoomDatastore().getCollection(getEntityClass());
		
		String mapStr = "function Map() { "   
	            + "var date = new Date(this.createTime*1000);" 
				+  "var year = date.getFullYear();"
				+  "var month = (\"0\" + (date.getMonth()+1)).slice(-2);"  //month 从0开始，此处要加1
				+  "var day = (\"0\" + date.getDate()).slice(-2);"
				+  "var hour = (\"0\" + date.getHours()).slice(-2);"
				+  "var minute = (\"0\" + date.getMinutes()).slice(-2);"
				+  "var dateStr = date.getFullYear()"+"+'-'+"+"(parseInt(date.getMonth())+1)"+"+'-'+"+"date.getDate();";
				
				if(counType==1){ // counType=1: 每个月的数据
					mapStr += "var key= year + '-'+ month;";
				}else if(counType==2){ // counType=2:每天的数据
					mapStr += "var key= year + '-'+ month + '-' + day;";
				}else if(counType==3){ //counType=3 :每小时数据
					mapStr += "var key= year + '-'+ month + '-' + day + '  ' + hour +' : 00';";
				}else if(counType==4){ //counType=4 :每分钟的数据
					mapStr += "var key= year + '-'+ month + '-' + day + '  ' + hour + ':'+ minute;";
				}
	           
				mapStr += "emit(key,1);}";
		
		 String reduce = "function Reduce(key, values) {" +
			                "return Array.sum(values);" +
	                    "}";
		 MapReduceCommand.OutputType type =  MapReduceCommand.OutputType.INLINE;
		 MapReduceCommand command = new MapReduceCommand(collection, mapStr, reduce,null, type,query);
		 
		 
		 MapReduceOutput mapReduceOutput = collection.mapReduce(command);
		 Iterable<DBObject> results = mapReduceOutput.results();
		 Map<String,Double> map = new HashMap<String,Double>();
		for (Iterator iterator = results.iterator(); iterator.hasNext();) {
			DBObject obj = (DBObject) iterator.next();
			 
			map.put((String)obj.get("_id"),(Double)obj.get("value"));
			countData.add(JSON.toJSON(map));
			map.clear();
			//System.out.println(JSON.toJSON(obj));
			
		}
		
		return countData;
	}
	
	/** @Description: 导出群成员
	* @param roomId
	* @param request
	* @param response
	* @return
	**/ 
	public Workbook exprotExcelGroupMembers(String roomId,HttpServletRequest request,HttpServletResponse response) {

		String name = getRoomName(new ObjectId(roomId))+" 的群成员明细";
		
		String fileName ="groupMembers.xlsx";

		List<Member> members = getMemberList(new ObjectId(roomId), null);
		List<String> titles = Lists.newArrayList();
		titles.add("userId");
		titles.add("userName");
		titles.add("remarkName");
		titles.add("telephone");
		titles.add("role");
		titles.add("offlineNoPushMsg");
		titles.add("createTime");
		titles.add("modifyTime");

		List<Map<String, Object>> values = Lists.newArrayList();
		members.forEach(member ->{
			Map<String, Object> map = Maps.newHashMap();
			map.put("userId", member.getUserId());
			map.put("userName", member.getNickname());
			map.put("remarkName", member.getRemarkName());
			map.put("telephone", getUserManager().getUser(member.getUserId()).getPhone());
			map.put("role", member.getRole() == 1 ?"群主":member.getRole() == 2 ? "管理员" : member.getRole() == 3?"普通成员":member.getRole() == 4 ? "隐身人" : "监护人");// 1=创建者、2=管理员、3=普通成员、4=隐身人、5=监控人
			map.put("offlineNoPushMsg", member.getOfflineNoPushMsg() == 0 ? "否" : "是");
			map.put("createTime", DateUtil.strToDateTime(member.getCreateTime()));
			map.put("modifyTime", DateUtil.strToDateTime(member.getModifyTime()));
			values.add(map);
		});

		Workbook workBook = ExcelUtil.generateWorkbook(name, "xlsx", titles, values);
		response.reset();
		try {
			response.setHeader("Content-Disposition",
					"attachment;filename=" + new String(fileName.getBytes(), "utf-8"));
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return workBook;
	}

	/** @Description: 分库分表保存用户加入的群组
	* @param userId
	* @param jid
	**/
	public void saveJidsByUserId(Integer userId,String jid,ObjectId roomId) {
		Document document = new Document();
		document.append("userId", userId).append("jid", jid).append("roomId", roomId);
		document.append("offlineNoPushMsg", 0);
		getCollection(userId).insertOne(document);
	}
	public void updateUserJidNoPushMsg(Integer userId,ObjectId roomId,int offlineNoPushMsg) {
		Document query = new Document();
		query.append("userId", userId).append("roomId", roomId);
		Document values = new Document("$set",new Document("offlineNoPushMsg", offlineNoPushMsg));
		getCollection(userId).updateOne(query, values);
	}

	/** 删除分库分表保存用户加入的群组
	 * @param userId
	 * @param jid
	 */
	public void delJidsByUserId(Integer userId,String jid) {
		Document document = new Document();
		document.append("userId", userId).append("jid", jid);
		getCollection(userId).deleteOne(document);

	}

	/** @Description:
	* @param user
	* @param roomId
	* @param userIdList
	**/
	public void consoleJoinRoom(User user, ObjectId roomId, List<Integer> userIdList){
		int i = 0;
		for (Integer userId : userIdList) {
			long currentTime = DateUtil.currentTimeSeconds();
			i++;
			currentTime+=i;
			Member data = SKBeanUtils.getRoomManagerImplForIM().getMember(roomId, userId);
			if(null != data)
				throw new ServiceException(userId+" 该成员已经在群组中,不能重复邀请");
			Member member = new Member();
			member.setActive(currentTime);
			member.setCreateTime(currentTime);
			member.setModifyTime(0L);
			member.setNickname(getUserManager().getNickName(userId));
			member.setRole(3);
			member.setRoomId(roomId);
			member.setSub(1);
			member.setTalkTime(0L);
			member.setUserId(userId);
			getDatastore().save(member);
			// 群组人数
			updateUserSize(roomId, 1);
			Room room = getRoom(roomId);

			// 发送单聊通知到被邀请人， 群聊
			sendNewMemberMessage(user.getUserId(),room,member);

			getRedisServiceImpl().deleteMemberList(roomId.toString());
			// 维护用户加入的群jids
			saveJidsByUserId(userId,room.getJid(),roomId);
			/**
			 * 删除 用户加入的群组 jid  缓存
			 */
			SKBeanUtils.getRedisService().deleteUserRoomJidList(member.getUserId());
			if(0==SKBeanUtils.getUserManager().getOnlinestateByUserId(member.getUserId())) {
				SKBeanUtils.getRedisService().addRoomPushMember(room.getJid(), member.getUserId());
			}
			// 维护群组数据
			getRedisServiceImpl().deleteRoom(String.valueOf(roomId));
		}
	}

	// 面对面创群
	public   Room queryLocationRoom(String name,double longitude,double latitude,String password,
			int isQuery){
		Integer userId = ReqUtil.getUserId();
		Room  room=SKBeanUtils.getRedisService().
				queryLocationRoom(userId, longitude, latitude, password, name);
		if(1==isQuery)
			return room;
		ThreadUtil.executeInThread(obj -> {
			for (Member mem : room.getMembers()) {
				if(userId.equals(mem.getUserId()))
					continue;
				MessageBean messageBean = new MessageBean();
				messageBean.setObjectId(room.getJid());
				messageBean.setFromUserId(userId.toString());
				messageBean.setFromUserName(userId.toString());
				messageBean.setType(KXMPPServiceImpl.LocationRoom);
				messageBean.setToUserId(mem.getUserId().toString());
				SKBeanUtils.getXmppService().send(messageBean);
			}
		});
		return room;
	}

	public synchronized Room joinLocationRoom(String roomJid) {
		ObjectId roomId = getRoomId(roomJid);
		Integer userId = ReqUtil.getUserId();
		User user=null;
		if(null==roomId) {
			Room room = SKBeanUtils.getRedisService().queryLocationRoom(roomJid);
			if(null==room)
				throw new ServiceException(KConstants.ResultCode.RoomTimeOut);
			user=SKBeanUtils.getUserManager().getUser(userId);
			roomId=new ObjectId();
			room.setId(roomId);
			add(user, room, null,null);

			SKBeanUtils.getRedisService().saveLocationRoom(roomJid,room);
		}else {
			user=SKBeanUtils.getUserManager().getUser(userId);
			Member member=new Member();
			member.setUserId(userId);
			updateMember(user, roomId, member);
		}
		return get(roomId);
	}

	public void exitLocationRoom(String roomJid) {
		Integer userId = ReqUtil.getUserId();
		SKBeanUtils.getRedisService().exitLocationRoom(userId, roomJid);
		ThreadUtil.executeInThread(new Callback() {

			@Override
			public void execute(Object obj) {
				Room room = SKBeanUtils.getRedisService().queryLocationRoom(roomJid);
				for (Member mem : room.getMembers()) {
					if(userId.equals(mem.getUserId()))
						continue;
					MessageBean messageBean = new MessageBean();
					messageBean.setObjectId(room.getJid());
					messageBean.setFromUserId(userId.toString());
					messageBean.setFromUserName(userId.toString());
					messageBean.setType(KXMPPServiceImpl.LocationRoom);
					messageBean.setToUserId(mem.getUserId().toString());
					SKBeanUtils.getXmppService().send(messageBean);
				}
			}
		});
	}

	/**
	 * 添加群助手
	 * @return
	 */
	public JSONMessage addGroupHelper(String helperId,String roomId,String roomJid,Integer userId){

		Query<GroupHelper> query = SKBeanUtils.getDatastore().createQuery(GroupHelper.class).field("roomId").equal(roomId).field("helperId").equal(helperId);
		if(null!=query.get()){
			return JSONMessage.failureByErrCode(KConstants.ResultCode.GroupHelperExist, ReqUtil.getRequestLanguage());
		}
		Query<Helper> helQuery = SKBeanUtils.getDatastore().createQuery(Helper.class).field("_id").equal(new ObjectId(helperId));
		if(null==helQuery.get()){
			return JSONMessage.failureByErrCode(KConstants.ResultCode.GroupHelperNotExist, ReqUtil.getRequestLanguage());
		}
		GroupHelper entity = new GroupHelper();
		entity.setHelperId(helperId);
		entity.setRoomId(roomId);
		entity.setRoomJid(roomJid);
		entity.setUserId(userId);
		if(null==entity.getId())
			entity.setId(ObjectId.get());
		SKBeanUtils.getDatastore().save(entity);
		entity.setHelper(helQuery.get());
		return JSONMessage.success(null, entity);
	}

	/**
	 * 添加自动回复关键字
	 * @param roomId
	 * @param helperId
	 * @param keyWord
	 * @param value
	 * @return
	 */
	public JSONMessage addAutoResponse(String roomId,String helperId,String keyWord,String value){
		Query<GroupHelper> query = SKBeanUtils.getDatastore().createQuery(GroupHelper.class).field("roomId").equal(roomId).field("helperId").equal(helperId);
		UpdateOperations<GroupHelper> ops = SKBeanUtils.getDatastore().createUpdateOperations(GroupHelper.class);

		GroupHelper.KeyWord keyword= new GroupHelper.KeyWord();
		keyword.setId(ObjectId.get().toString());
		keyword.setKeyWord(keyWord);
		keyword.setValue(value);

		List<KeyWord> list = new ArrayList<>();

		GroupHelper groupHelper = query.get();
		if(null==groupHelper){
			return JSONMessage.failureByErrCode(KConstants.ResultCode.GroupHelperNotExist, ReqUtil.getRequestLanguage());
		}

		if(null!=groupHelper.getKeywords()){
			for(int i=0;i<groupHelper.getKeywords().size();i++){
				if(groupHelper.getKeywords().get(i).getKeyWord().equals(keyWord)){
					return JSONMessage.failureByErrCode(KConstants.ResultCode.KeyWordIsExist, ReqUtil.getRequestLanguage());
				}
			}
			groupHelper.getKeywords().add(keyword);
		}else{
			list.add(keyword);
			groupHelper.setKeywords(list);
		}

		ops.set("keywords", groupHelper.getKeywords());
		SKBeanUtils.getDatastore().update(query, ops);
		return JSONMessage.success(null, keyword);

	}

	/**
	 * 修改自动回复关键字和回复
	 * @param keyWordId
	 * @param keyword
	 * @param value
	 */
	public JSONMessage updateKeyword(String groupHelperId,String keyWordId,String keyword,String value){
		Query<GroupHelper> query = SKBeanUtils.getDatastore().createQuery(GroupHelper.class).field("_id").equal(new ObjectId(groupHelperId));
		UpdateOperations<GroupHelper> ops=SKBeanUtils.getDatastore().createUpdateOperations(GroupHelper.class);
		GroupHelper groupHelper =query.get();
		if(null==groupHelper){
			return JSONMessage.failureByErrCode(KConstants.ResultCode.GroupHelperNotExist, ReqUtil.getRequestLanguage());
		}
		if(null==groupHelper.getKeywords()){
			return JSONMessage.failureByErrCode(KConstants.ResultCode.KeyWordNotExist, ReqUtil.getRequestLanguage());
		}
		for(int i=0;i<groupHelper.getKeywords().size();i++){
			if(groupHelper.getKeywords().get(i).getId().equals(keyWordId)){
				groupHelper.getKeywords().get(i).setKeyWord(keyword);
				groupHelper.getKeywords().get(i).setValue(value);
			}
		}
		ops.set("keywords", groupHelper.getKeywords());
		SKBeanUtils.getDatastore().update(query, ops);
		return JSONMessage.success();
	}

	/**
	 * 删除自动回复关键字
	 * @param groupHelperId
	 * @param keyWordId
	 */
	public JSONMessage deleteAutoResponse(Integer userId,String groupHelperId,String keyWordId){
		Query<GroupHelper> query = SKBeanUtils.getDatastore().createQuery(GroupHelper.class).field("_id").equal(new ObjectId(groupHelperId)).field("userId").equal(userId);
		UpdateOperations<GroupHelper> ops=SKBeanUtils.getDatastore().createUpdateOperations(GroupHelper.class);
		GroupHelper groupHelper = query.get();
		if(null==groupHelper){
			return JSONMessage.failureByErrCode(KConstants.ResultCode.GroupHelperNotExist, ReqUtil.getRequestLanguage());
		}
		if(null==groupHelper.getKeywords()){
			return JSONMessage.failureByErrCode(KConstants.ResultCode.KeyWordNotExist, ReqUtil.getRequestLanguage());
		}
		for(int i=0;i<groupHelper.getKeywords().size();i++){
			if(groupHelper.getKeywords().get(i).getId().equals(keyWordId)){
				groupHelper.getKeywords().remove(i);
			}
		}
		ops.set("keywords", groupHelper.getKeywords());
		SKBeanUtils.getDatastore().update(query, ops);
		return JSONMessage.success();
	}

	/**
	 * 删除群助手
	 * @param id
	 */
	public void deleteGroupHelper(Integer userId,String id){
		Query<GroupHelper> query = SKBeanUtils.getDatastore().createQuery(GroupHelper.class).field("_id").equal(new ObjectId(id)).field("userId").equal(userId);
		WriteResult delete = SKBeanUtils.getDatastore().delete(query);
		if(delete.getN()<=0){
			throw new ServiceException(KConstants.ResultCode.DeleteFailure);
		}
	}

	/**
	 * 查询群组群助手
	 * @param roomId
	 * @return
	 */
	public List<GroupHelper> queryGroupHelper(String roomId,String helperId){
		Query<GroupHelper> query = SKBeanUtils.getDatastore().createQuery(GroupHelper.class).field("roomId").equal(roomId);
		List<GroupHelper> list= query.asList();
		List<GroupHelper> newList = new ArrayList<>();
		if(!StringUtil.isEmpty(helperId)){
			for(int i=0;i<list.size();i++){
				if(list.get(i).getHelperId().equals(helperId)){
					Query<Helper> q = SKBeanUtils.getDatastore().createQuery(Helper.class).field("_id").equal(new ObjectId(list.get(i).getHelperId()));
					list.get(i).setHelper(q.get());
					newList.add(list.get(i));
				}
			}
		}else{
			for(int i=0;i<list.size();i++){
				Query<Helper> q = SKBeanUtils.getDatastore().createQuery(Helper.class).field("_id").equal(new ObjectId(list.get(i).getHelperId()));
				if(null!=q.get()){
					list.get(i).setHelper(q.get());
					newList.add(list.get(i));
				}
			}
		}

		return newList;

	}

	/** @Description:多点登录下修改群组相关信息
	* @param userId
	* @param nickName
	* @param toUserId
	* @param toNickName
	* @param roomId
	**/
	public void multipointLoginUpdateUserInfo(Integer userId,String nickName,Integer toUserId,String toNickName,ObjectId roomId){
		Datastore datastore = SKBeanUtils.getDatastore();
		updateRoomInfo(userId, nickName,toUserId,toNickName,roomId);
		Query<OfflineOperation> query = datastore.createQuery(OfflineOperation.class).field("userId").equal(userId);
		query.field("friendId").equal(String.valueOf(roomId));
		if(null == query.get())
			datastore.save(new OfflineOperation(userId, KConstants.MultipointLogin.TAG_ROOM, String.valueOf(roomId), DateUtil.currentTimeSeconds()));
		else{
			UpdateOperations<OfflineOperation> ops = datastore.createUpdateOperations(OfflineOperation.class);
			ops.set("operationTime", DateUtil.currentTimeSeconds());
			datastore.update(query, ops);
		}
	}

	/** @Description:多点登录下修改群组相关信息通知
	* @param userId
	* @param nickName
	**/
	public void updateRoomInfo(Integer userId,String nickName,Integer toUserId,String toNickName,ObjectId roomId){
		ThreadUtil.executeInThread(new Callback() {
			@Override
			public void execute(Object obj) {
					MessageBean messageBean = new MessageBean();
					messageBean.setType(KXMPPServiceImpl.updateRoomInfo);
					messageBean.setFromUserId(String.valueOf(userId));
					messageBean.setFromUserName(nickName);
					messageBean.setToUserId(String.valueOf(roomId));
					messageBean.setToUserName(getRoomName(roomId));
					messageBean.setMessageId(StringUtil.randomUUID());
					messageBean.setTo(String.valueOf(userId));
					try {
						KXMPPServiceImpl.getInstance().send(messageBean);
					} catch (Exception e) {
						e.printStackTrace();
					}
			}
		});
	}


	/**
	 * 后台管理员删除群组消息
	 * @param roomJid
	 * @param type
	 * @return
	 */
	public void adminDeleteRoomMsg( String roomJid, int type) {

		MongoCollection<Document> dbCollection = getImRoomDatabase().getCollection(DBConstants.RoomMsg_Collection_Prefix + roomJid);
		Document query = new Document();
		dbCollection.createIndex(new Document("timeSend",-1));
		if ( 0 == type ) { //删除一个月前的聊天记录

			long onedayNextDay = DateUtil.getOnedayNextDay(DateUtil.currentTimeSeconds(), 30, 1);
			logger.info("上个月的时间：" + onedayNextDay);
			query.append("timeSend", new Document("$lte", onedayNextDay*1000));

		} else if (1 == type) { //删除十万条前的聊天记录

			final int num = 100000;
			long count = dbCollection.count();
			if (count <= num)
				throw new ServiceException("该群的消息总数量小于" + num);
			Document first = dbCollection.find().sort(new Document("timeSend", -1)).skip(num).first();
			if(null==first)
				return;
			query.append("timeSend",new Document(MongoOperator.LT, first.getLong("timeSend")));
		}
		//把文件 url 加到要删除的文件记录表中,用以删除文件
		SKBeanUtils.getTigaseManager().joinFileUriToDelFielsCollection(dbCollection,query);
	    //删除群组聊天记录
		dbCollection.deleteMany(query);

	}


	public Room copyRoom(User user,String roomId){
		ObjectId objRoomId = new ObjectId(roomId);
		Room room = getRoom(objRoomId,user.getUserId());
		List<Integer> memberIdList = getMemberIdList(objRoomId);
		memberIdList.remove(user.getUserId());
		room.setId(new ObjectId());

		room.setJid(StringUtil.randomUUID());
		Room newRoom = add(user, room, memberIdList,null);
		return newRoom;
	}

	private  class  createRoomImg implements com.shiku.commons.thread.Callback {

		private String mUserList = "";
		private String mJid = "";
		private int errCount = 0;
		public  createRoomImg(String szUserList,String jid)
		{
			this.mUserList= szUserList;
			this.mJid = jid;
			this.errCount = 0;
		}
		@Override
		public void execute(Object obj) {
			try {
				SortedMap<String, String> contentMap = new TreeMap<String, String>();
				contentMap.put("UserList",this.mUserList);
				contentMap.put("jid",this.mJid);
				String jsonParms = JSONObject.toJSONString(contentMap);
				//取出通知地址
				String funUrl= SKBeanUtils.getLocalSpringBeanManager().getAppConfig().getRoomImgCreateUrl();
				HttpClientUtil.sendJsonMessage(funUrl,JSONObject.parseObject(jsonParms));

			}catch (Exception e) {
				if(errCount < 5)
				{
					this.errCount++;
					ThreadUtils.executeInThread(this,30);
				}
				e.printStackTrace();
			}
		}
	}
}
